Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. What is the correct way of paint my own background of widgets?
QtWS25 Last Chance

What is the correct way of paint my own background of widgets?

Scheduled Pinned Locked Moved Unsolved General and Desktop
9 Posts 4 Posters 2.8k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    Manifolds
    wrote on last edited by Manifolds
    #1
    void XXX::resizeEvent(QResizeEvent *event)
    {
        const QString& txt = pdt->txt;
        if(txt.length()==0) return;
        int h = height();
        int w = width();
        int nw = this->fontMetrics().width(txt) + 1.25*h;
        if(nw>w){
            resize(nw,h);
        }
    }
    void XXX::paintEvent(QPaintEvent*)
    {
        int h = height();
        int w = width();
        QFont font = this->font();
        font.setPixelSize(h/2);
        this->setFont(font);
        //
        QPainterPath path;
        path.setFillRule(Qt::WindingFill);
        path.moveTo(h/2,0);
        path.arcTo(0,0, h,h, 90, 180);
        path.lineTo(w-h/2, h);
        path.arcTo(w-h,0, h,h, 270,180);
        path.closeSubpath();
        //
        QPainter painter;
        painter.begin(this);
        painter.setRenderHint(QPainter::Antialiasing);
        painter.fillPath(path, pdt->currentBackgroundColor);
        QBrush brsh;
        brsh.setColor(Qt::black);
        painter.setBrush(brsh);
        if(pdt->txt.size()>0)
           painter.drawText(QPointF(h/2,2*h/3), pdt->txt);
        painter.end();
    }
    

    Above code is my way of painting background of Label widget.

    When I dynamically push more then one this widgets to QHBoxLayout, these labels will be partially overlaped with nearest labels.

    The next label's begin pos() is in previous label's paint region.

    My OS is macOS 10.12.5, My Qt Version is 5.9 Official.

    raven-worxR 1 Reply Last reply
    0
    • M Manifolds
      void XXX::resizeEvent(QResizeEvent *event)
      {
          const QString& txt = pdt->txt;
          if(txt.length()==0) return;
          int h = height();
          int w = width();
          int nw = this->fontMetrics().width(txt) + 1.25*h;
          if(nw>w){
              resize(nw,h);
          }
      }
      void XXX::paintEvent(QPaintEvent*)
      {
          int h = height();
          int w = width();
          QFont font = this->font();
          font.setPixelSize(h/2);
          this->setFont(font);
          //
          QPainterPath path;
          path.setFillRule(Qt::WindingFill);
          path.moveTo(h/2,0);
          path.arcTo(0,0, h,h, 90, 180);
          path.lineTo(w-h/2, h);
          path.arcTo(w-h,0, h,h, 270,180);
          path.closeSubpath();
          //
          QPainter painter;
          painter.begin(this);
          painter.setRenderHint(QPainter::Antialiasing);
          painter.fillPath(path, pdt->currentBackgroundColor);
          QBrush brsh;
          brsh.setColor(Qt::black);
          painter.setBrush(brsh);
          if(pdt->txt.size()>0)
             painter.drawText(QPointF(h/2,2*h/3), pdt->txt);
          painter.end();
      }
      

      Above code is my way of painting background of Label widget.

      When I dynamically push more then one this widgets to QHBoxLayout, these labels will be partially overlaped with nearest labels.

      The next label's begin pos() is in previous label's paint region.

      My OS is macOS 10.12.5, My Qt Version is 5.9 Official.

      raven-worxR Offline
      raven-worxR Offline
      raven-worx
      Moderators
      wrote on last edited by
      #2

      @Manifolds said in What is the correct way of paint my own background of widgets?:

      When I dynamically push more then one this widgets to QHBoxLayout, these labels will be partially overlaped with nearest labels.
      The next label's begin pos() is in previous label's paint region.

      I do not quite understand this?! QHBoxlayout doesn't layout widgets overlapped.
      Normally you shouldn't be able to paint outside of the widget unless you have set some attributes (e.g. Qt::WA_PaintUnclipped) on the widget to paint outside of the clip region?

      Nevertheless you may want to try:

      painter.setClipRect( this->rect() );
      

      --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
      If you have a question please use the forum so others can benefit from the solution in the future

      M 1 Reply Last reply
      0
      • raven-worxR raven-worx

        @Manifolds said in What is the correct way of paint my own background of widgets?:

        When I dynamically push more then one this widgets to QHBoxLayout, these labels will be partially overlaped with nearest labels.
        The next label's begin pos() is in previous label's paint region.

        I do not quite understand this?! QHBoxlayout doesn't layout widgets overlapped.
        Normally you shouldn't be able to paint outside of the widget unless you have set some attributes (e.g. Qt::WA_PaintUnclipped) on the widget to paint outside of the clip region?

        Nevertheless you may want to try:

        painter.setClipRect( this->rect() );
        
        M Offline
        M Offline
        Manifolds
        wrote on last edited by
        #3

        @raven-worx
        painter.setClipRect( this->rect() );

        can't solve my problem.

        I just want to design a label widget that have any shape border and any color fill.
        I guess the reason is that, when I add the widget to the layout, it hasn't resize correctly, ie. reimplement the resizeEvent function is not enough.

        1 Reply Last reply
        0
        • M Offline
          M Offline
          Manifolds
          wrote on last edited by Manifolds
          #4

          TEST CODE :
          https://drive.google.com/file/d/0B5KhqCB2t4oGRGZUdTJ2b0doeHc/view?usp=sharing

          alt text

          FlotisableF 1 Reply Last reply
          0
          • M Manifolds

            TEST CODE :
            https://drive.google.com/file/d/0B5KhqCB2t4oGRGZUdTJ2b0doeHc/view?usp=sharing

            alt text

            FlotisableF Offline
            FlotisableF Offline
            Flotisable
            wrote on last edited by
            #5

            @Manifolds
            I think you should not use resize() in resizeEvent(), the QHBoxLayout will handle the size of the widgets, the overlap may be caused by your resize.

            1 Reply Last reply
            0
            • Chris KawaC Online
              Chris KawaC Online
              Chris Kawa
              Lifetime Qt Champion
              wrote on last edited by
              #6

              You definitely shouldn't call resize() from resizeEvent(), paintEvent() or most other event handlers for that matter.
              A better way to handle overflowing text is to elide it. You also don't need path rendering to draw a rounded rectangle. There's a dedicated method for that. You also shouldn't change the widget's font from the paintEvent. Change the painter's font instead.
              For example:

              void ShapedTag::paintEvent(QPaintEvent*)
              {
                  int radius = height() /2;
              
                  QPainter p(this);
                  p.setRenderHint(QPainter::Antialiasing);
                  p.setBrush(pdt->currentBackgroundColor);
                  p.setPen(Qt::transparent);
                  p.drawRoundedRect(rect(), radius, radius);
              
                  QFont f = font();
                  f.setPixelSize(radius);
                  p.setFont(f);
              
                  QRect textRect = rect().adjusted(radius, 0, -radius, 0);
                  QString text = QFontMetrics(f).elidedText(pdt->txt, Qt::ElideRight, textRect.width());
                  p.setPen(Qt::black);
                  p.drawText(textRect, Qt::AlignCenter | Qt::TextSingleLine, text);
              }
              

              If you don't want to elide the text you should rather calculate the size of the font based on the width, rather than height and then implement hasHeightForWidth() and heightForWidth() to make it proportional.

              1 Reply Last reply
              3
              • M Offline
                M Offline
                Manifolds
                wrote on last edited by
                #7

                @Chris-Kawa said in What is the correct way of paint my own background of widgets?:

                void ShapedTag::paintEvent(QPaintEvent*)
                {
                int radius = height() /2;

                QPainter p(this);
                p.setRenderHint(QPainter::Antialiasing);
                p.setBrush(pdt->currentBackgroundColor);
                p.setPen(Qt::transparent);
                p.drawRoundedRect(rect(), radius, radius);
                
                QFont f = font();
                f.setPixelSize(radius);
                p.setFont(f);
                
                QRect textRect = rect().adjusted(radius, 0, -radius, 0);
                QString text = QFontMetrics(f).elidedText(pdt->txt, Qt::ElideRight, textRect.width());
                p.setPen(Qt::black);
                p.drawText(textRect, Qt::AlignCenter | Qt::TextSingleLine, text);
                

                }

                Thank you for your reply.

                I want to design a uiLabel like label, it can auto resize the width that according my text content.
                Your solution can seperate the labels, but all the labels are have the same width if I do not calculate and set the layout stretches.

                1 Reply Last reply
                0
                • Chris KawaC Online
                  Chris KawaC Online
                  Chris Kawa
                  Lifetime Qt Champion
                  wrote on last edited by Chris Kawa
                  #8

                  Right, so you can't elide the text if that's the effect you want.
                  You'll have to put some constraints on your label.
                  It can't have a dynamic font size because that changes the width of the text, which changes height of the label proportionally, which changes font size, which changes text width, which changes height of the label... I hope you see where this is going ;)

                  So if you don't adjust font size dynamically all you have to do is implement minimumSizeHint() and return the calculated width of the text + the rounded rectangle margins.

                  M 1 Reply Last reply
                  1
                  • Chris KawaC Chris Kawa

                    Right, so you can't elide the text if that's the effect you want.
                    You'll have to put some constraints on your label.
                    It can't have a dynamic font size because that changes the width of the text, which changes height of the label proportionally, which changes font size, which changes text width, which changes height of the label... I hope you see where this is going ;)

                    So if you don't adjust font size dynamically all you have to do is implement minimumSizeHint() and return the calculated width of the text + the rounded rectangle margins.

                    M Offline
                    M Offline
                    Manifolds
                    wrote on last edited by
                    #9

                    @Chris-Kawa

                    I follow your instruction and succeed.

                    But It's not so smart, I will spend some time to read QT Source, and find out how the QLabel class being designed.

                    I manually add height and font point size to the ShapedTag, and the function setText will calculate the widget width, and at last in funtion minimumSizeHint return the QSize I have calculated.

                    1 Reply Last reply
                    0

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved