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. Custom QStyle for QLabel: Issue with Double Text Rendering

Custom QStyle for QLabel: Issue with Double Text Rendering

Scheduled Pinned Locked Moved Solved General and Desktop
5 Posts 3 Posters 679 Views 1 Watching
  • 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.
  • B Offline
    B Offline
    Boltian
    wrote on last edited by
    #1

    Hi,
    I'm working on creating a custom QStyle for a QLabel without relying on style sheets.
    I've successfully implemented a similar approach for customizing a button's style, and it works as expected.
    However, when applying it to the label, I'm encountering an issue where the label renders two overlapping instances of the text.

    The issue I'm facing is that the label renders two instances of the text.
    The first one is painted according to the custom requirements from the code, but the default text rendered by QLabel remains visible and is not removed.
    I need to prevent the default rendering and only show the customized version.

    Capture.PNG

    void AstraLabelStyle::draw(const QStyleOption* option, QPainter* p, const QWidget* widget) const
    {  
        QWidget* nonConstWidget = const_cast<QWidget*>(widget);
        QLabel* label = dynamic_cast<QLabel*>(nonConstWidget);
    
        mTheme->getState(option);
    
        // Sub Elements
        QString text = label->text();
    
        // Font
        QFont font(mTheme->fontFamily(), 20, mTheme->fontWeight());
        
        // Compute the total size of subelements
        QSize eSize;
        int eSpacing;
        computeElementsSize(option, label, font, eSize, eSpacing);
    
        QRect rect = option->rect;
        
        // -------------------------------------------------------------------------------------------------------------
        int x = rect.x() + mTheme->paddingH(); ;
        int y = rect.y() + (rect.height() - eSize.height()) / 2;
    
        // Text
        if (!text.isEmpty())
        {
            p->save();
            p->setRenderHint(QPainter::TextAntialiasing, true);
            QRect textRect(x, y + (eSize.height() - option->fontMetrics.height()) / 2, option->fontMetrics.horizontalAdvance(text) * 1.5, option->fontMetrics.height());
            p->setPen(QPen(QBrush(mTheme->foregroundBrush(textRect)), 1));
            p->setFont(font);
            p->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, text);
            p->restore();
            
        }
    }
    

    Thanks in advance for your help.

    Pl45m4P 1 Reply Last reply
    0
    • B Offline
      B Offline
      Boltian
      wrote on last edited by
      #5

      At the end I have found the folowing solution:
      Now just one text rendering is performed.

      void AstraApplicationStyle::drawItemText(QPainter* painter, const QRect& rect, int flags, const QPalette& pal, bool enabled, const QString& text, QPalette::ColorRole textRole) const
      {
      	if (text.isEmpty() || skipLabelTextRendering) 
      	{
      		skipLabelTextRendering = false;
      		return; 
      	}
      
      	QProxyStyle::drawItemText(painter, rect, flags, pal, enabled, text, textRole);
      }
      
      void AstraApplicationStyle::drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
      {
      	//qDebug() << "--> Widget Name: " << widget->objectName() << " (CE: " << element << ")";
      
      	QString name = widget->objectName();
      	switch (element)
      	{
      		case QStyle::CE_ShapedFrame:
      		{
      			// QLabel
      			if (widget && qobject_cast<const QLabel*>(widget))
      			{
      				skipLabelTextRendering = true;
      				mLabelStyle->draw(option, painter, widget);
      				return;
      			}
      			break;
      		}
      		case QStyle::CE_PushButton:
      		{
      			mButtonStyle->draw(option, painter, widget);
      			return;
      		}
      		default:
      			break;
      	}
      
      	//Base
      	QProxyStyle::drawControl(element, option, painter, widget);
      }
      
      
      
      1 Reply Last reply
      0
      • Christian EhrlicherC Online
        Christian EhrlicherC Online
        Christian Ehrlicher
        Lifetime Qt Champion
        wrote on last edited by
        #2

        Who calls draw()? It's not a virtual function of QStyle.

        Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
        Visit the Qt Academy at https://academy.qt.io/catalog

        B 1 Reply Last reply
        1
        • B Boltian

          Hi,
          I'm working on creating a custom QStyle for a QLabel without relying on style sheets.
          I've successfully implemented a similar approach for customizing a button's style, and it works as expected.
          However, when applying it to the label, I'm encountering an issue where the label renders two overlapping instances of the text.

          The issue I'm facing is that the label renders two instances of the text.
          The first one is painted according to the custom requirements from the code, but the default text rendered by QLabel remains visible and is not removed.
          I need to prevent the default rendering and only show the customized version.

          Capture.PNG

          void AstraLabelStyle::draw(const QStyleOption* option, QPainter* p, const QWidget* widget) const
          {  
              QWidget* nonConstWidget = const_cast<QWidget*>(widget);
              QLabel* label = dynamic_cast<QLabel*>(nonConstWidget);
          
              mTheme->getState(option);
          
              // Sub Elements
              QString text = label->text();
          
              // Font
              QFont font(mTheme->fontFamily(), 20, mTheme->fontWeight());
              
              // Compute the total size of subelements
              QSize eSize;
              int eSpacing;
              computeElementsSize(option, label, font, eSize, eSpacing);
          
              QRect rect = option->rect;
              
              // -------------------------------------------------------------------------------------------------------------
              int x = rect.x() + mTheme->paddingH(); ;
              int y = rect.y() + (rect.height() - eSize.height()) / 2;
          
              // Text
              if (!text.isEmpty())
              {
                  p->save();
                  p->setRenderHint(QPainter::TextAntialiasing, true);
                  QRect textRect(x, y + (eSize.height() - option->fontMetrics.height()) / 2, option->fontMetrics.horizontalAdvance(text) * 1.5, option->fontMetrics.height());
                  p->setPen(QPen(QBrush(mTheme->foregroundBrush(textRect)), 1));
                  p->setFont(font);
                  p->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, text);
                  p->restore();
                  
              }
          }
          

          Thanks in advance for your help.

          Pl45m4P Offline
          Pl45m4P Offline
          Pl45m4
          wrote on last edited by Pl45m4
          #3

          @Boltian said in Custom QStyle for QLabel: Issue with Double Text Rendering:

          // Text
          if (!text.isEmpty())
          {
              p->save();
              p->setRenderHint(QPainter::TextAntialiasing, true);
              QRect textRect(x, y + (eSize.height() - option->fontMetrics.height()) / 2, option->fontMetrics.horizontalAdvance(text) * 1.5, option->fontMetrics.height());
              p->setPen(QPen(QBrush(mTheme->foregroundBrush(textRect)), 1));
              p->setFont(font);
              p->drawText(textRect, Qt::AlignLeft | Qt::AlignVCenter, text);
              p->restore();
              
          }
          

          Hi,

          I'm not an expert when it comes to custom QStyle implementations, but I wonder what happens, when you remove the save / restore calls?

          Edit:

          As @Christian-Ehrlicher said above:
          Check the source for QLabel style:

          In paintEvent the style->drawItemText is called

          • https://codebrowser.dev/qt6/qtbase/src/widgets/widgets/qlabel.cpp.html#1063

          and internally drawItemText paints with painter->drawText

          • https://codebrowser.dev/qt6/qtbase/src/widgets/styles/qstyle.cpp.html#593

          If debugging is the process of removing software bugs, then programming must be the process of putting them in.

          ~E. W. Dijkstra

          1 Reply Last reply
          0
          • Christian EhrlicherC Christian Ehrlicher

            Who calls draw()? It's not a virtual function of QStyle.

            B Offline
            B Offline
            Boltian
            wrote on last edited by
            #4

            @Christian-Ehrlicher

            The draw() method is call up in the general style.
            mLabelStyle is a a helper which contains all necessry methods for define the style.

            void AstraApplicationStyle::drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
            {
            	QString name = widget->objectName();
            	switch (element)
            	{
            		case QStyle::CE_ShapedFrame:
            		{
            			// QLabel
            			if (widget && qobject_cast<const QLabel*>(widget))
            			{
            				mLabelStyle->draw(option, painter, widget);
            				return;
            			}
            			
            			break;
            		}
            		case QStyle::CE_PushButton:
            		{
            			mButtonStyle->draw(option, painter, widget);
            			return;
            		}
            		default:
            			break;
            	}
            
            	//Base
            	QProxyStyle::drawControl(element, option, painter, widget);
            }
            
            1 Reply Last reply
            0
            • B Offline
              B Offline
              Boltian
              wrote on last edited by
              #5

              At the end I have found the folowing solution:
              Now just one text rendering is performed.

              void AstraApplicationStyle::drawItemText(QPainter* painter, const QRect& rect, int flags, const QPalette& pal, bool enabled, const QString& text, QPalette::ColorRole textRole) const
              {
              	if (text.isEmpty() || skipLabelTextRendering) 
              	{
              		skipLabelTextRendering = false;
              		return; 
              	}
              
              	QProxyStyle::drawItemText(painter, rect, flags, pal, enabled, text, textRole);
              }
              
              void AstraApplicationStyle::drawControl(ControlElement element, const QStyleOption* option, QPainter* painter, const QWidget* widget) const
              {
              	//qDebug() << "--> Widget Name: " << widget->objectName() << " (CE: " << element << ")";
              
              	QString name = widget->objectName();
              	switch (element)
              	{
              		case QStyle::CE_ShapedFrame:
              		{
              			// QLabel
              			if (widget && qobject_cast<const QLabel*>(widget))
              			{
              				skipLabelTextRendering = true;
              				mLabelStyle->draw(option, painter, widget);
              				return;
              			}
              			break;
              		}
              		case QStyle::CE_PushButton:
              		{
              			mButtonStyle->draw(option, painter, widget);
              			return;
              		}
              		default:
              			break;
              	}
              
              	//Base
              	QProxyStyle::drawControl(element, option, painter, widget);
              }
              
              
              
              1 Reply Last reply
              0
              • B Boltian has marked this topic as solved on

              • Login

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