Results 1 to 2 of 2

Thread: Style aware custom Widget

  1. #1
    Join Date
    Feb 2017
    Posts
    2
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Style aware custom Widget

    Hello,
    I've been programming with Qt since a while but I've never played around with Stylesheets and style aware widgets. I was trying to create a custom title bar for my application, and I wanted its appearance to be defined by a stylesheet.
    Reading the documentation and googling here and there I've understood that I cannot define a really custom stylesheet for my Widget. My ideal result would have been something like this:

    Qt Code:
    1. CustomTitlebar
    2. {
    3. application-icon: url(:/icons/appicon.png);
    4. background-color: #999999;
    5. background-color-hover: #DDDDDD;
    6. minimize-icon: url(:/icons/minimize.png);
    7. maximize-icon: url(:/icons/maximize.png);
    8. close-icon: url(:/icons/close.png);
    9. text-color: #000000;
    10. }
    To copy to clipboard, switch view to plain text mode 

    But it seems that I can only reuse QSS property names already defined for the base Widgets. I'm having a hard time finding all the fields I need, in fact I found only the following 2 matching:

    Qt Code:
    1. CustomTitlebar
    2. {
    3. background-color: #999999;
    4. color: #000000;
    5. }
    To copy to clipboard, switch view to plain text mode 

    On my CustomTitlebar paintEvent function I'm using the styles drawing primitives:

    Qt Code:
    1. void CustomTitleBar::paintEvent ( QPaintEvent *event )
    2. {
    3. QPainter painter (this);
    4.  
    5. QStyleOption styleOption;
    6. styleOption.init (this);
    7.  
    8. style ()->drawPrimitive (QStyle::PE_Widget, &styleOption, &painter, this);
    9. style ()->drawItemText (&painter, rect (), Qt::AlignCenter, styleOption.palette, true, mTitle);
    10.  
    11. if (mMouseOverCloseButtonFlag == true)
    12. {
    13. painter.save ();
    14. painter.setPen (Qt::transparent);
    15. painter.setBrush (mBrushHover);
    16. painter.drawRect (width () - s_iButtonWidth - 1, 1, s_iButtonWidth, s_iButtonWidth - 1);
    17. painter.restore ();
    18. }
    19.  
    20. if (mMouseOverMinimizeButtonFlag == true)
    21. {
    22. painter.save ();
    23. painter.setPen (Qt::transparent);
    24. painter.setBrush (mBrushHover);
    25. painter.drawRect (width () - s_iButtonWidth * 2 - 1, 1, s_iButtonWidth, s_iButtonWidth - 1);
    26. painter.restore ();
    27. }
    28.  
    29. style ()->drawItemText (&painter, QRect (width () - s_iButtonWidth * 2, 0, s_iButtonWidth, s_iButtonWidth), Qt::AlignCenter, styleOption.palette, true, "_");
    30.  
    31. style ()->drawItemText (&painter, QRect (width () - s_iButtonWidth, 0, s_iButtonWidth, s_iButtonWidth), Qt::AlignCenter, styleOption.palette, true, "X");
    32. }
    To copy to clipboard, switch view to plain text mode 

    As you can see I had to hardcode quite a lot of things. I find frustrating having to use those few styled painting primitives, or (as I hope) there's something I'm missing and there's a nice, clean way to make a complex style aware custom widget. I thought I could come up with a paintEvent code more like this, totally controlled by the StyleSheet:

    Qt Code:
    1. void CustomTitleBar::paintEvent ( QPaintEvent *event )
    2. {
    3. QPainter painter (this);
    4.  
    5. QStyleOption styleOption;
    6. styleOption.init (this);
    7.  
    8. style ()->drawPrimitive (QStyle::PE_Widget, &styleOption, &painter, this);
    9. style ()->drawItemText (&painter, rect (), Qt::AlignCenter, styleOption.palette, true, mTitle);
    10.  
    11. QRect rect1 (width () - s_iButtonWidth - 1, 1, s_iButtonWidth, s_iButtonWidth - 1);
    12. QRect rect2 (width () - s_iButtonWidth - 1, 1, s_iButtonWidth, s_iButtonWidth - 1);
    13.  
    14. if (mMouseOverCloseButtonFlag == true)
    15. {
    16. style ()->drawRect (&painter, rect1, "CustomTitlebar::background-color-hover");
    17. }
    18.  
    19. if (mMouseOverMinimizeButtonFlag == true)
    20. {
    21. style ()->drawRect (&painter, rect2, "CustomTitlebar::background-color-hover");
    22. }
    23.  
    24. style ()->drawItemPixmap (&painter, rect1, Qt::AlignRight, "CustomTitlebar::close-icon");
    25. style ()->drawItemPixmap (&painter, rect2, Qt::AlignRight, "CustomTitlebar::minimize-icon");
    26. }
    To copy to clipboard, switch view to plain text mode 

    I know I made up some non existing methods, but it was just to give an idea on how I thought it could be implemented.
    Is there a way to do something like this or I have to start hardcoding stuff inside the paintEvent, losing the separation between StyleSheet and C++ code?

    Thanks for your time!

  2. #2
    Join Date
    Feb 2017
    Posts
    2
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Re: Style aware custom Widget

    Answering myself after running into the solution almost by accident. The key lies into the "qproperty-" syntax supported by Qt StyleSheets. You can define a stylesheet like this one:

    Qt Code:
    1. CustomTitlebar
    2. {
    3. qproperty-application-icon: url(:/icons/appicon.png);
    4. qproperty-backgroundColor: #999999;
    5. qproperty-backgroundColorHover: #DDDDDD;
    6. qproperty-minimizeIcon: url(:/icons/minimize.png);
    7. qproperty-maximizeIcon: url(:/icons/maximize.png);
    8. qproperty-closeIcon: url(:/icons/close.png);
    9. qproperty-textColor: #000000;
    10. }
    To copy to clipboard, switch view to plain text mode 

    With all those wonderful custom style fields. In your custom widget's C++ code, you have to do the following in the Header file:

    Qt Code:
    1. class CustomTitleBar : public QWidget
    2. {
    3. Q_OBJECT
    4. Q_PROPERTY(QColor backgroundColorHover READ getBackgroundColorHover WRITE setBackgroundColorHover DESIGNABLE true)
    5. Q_PROPERTY(QColor backgroundColor READ getBackgroundColor WRITE setBackgroundColor DESIGNABLE true)
    6. // Every other custom style field shall be defined here as Q_PROPERTY with READ and WRITE methods
    7.  
    8. public:
    9.  
    10. QColor getBackgroundColorHover () const;
    11.  
    12. void setBackgroundColorHover ( QColor c );
    13.  
    14. QColor getBackgroundColor () const;
    15.  
    16. void setBackgroundColor ( QColor c );
    17.  
    18. // Every other READ/WRITE method shall be declared here...
    19.  
    20. private:
    21.  
    22. QColor backgroundColor;
    23. QColor backgroundColorHover;
    24.  
    25. // Every other READ/WRITE property shall be declared here...
    26.  
    27. };
    To copy to clipboard, switch view to plain text mode 

    The implementation of READ/WRITE methods is trivial, you just get/set the proper fields.
    And finally the paintEvent function shall draw in the old-fashioned way using QPainter, but using the Q_PROPERTIES defined earlier:

    Qt Code:
    1. void CustomTitleBar::paintEvent ( QPaintEvent *event )
    2. {
    3. QPainter painter (this);
    4. QBrush brushHover = QBrush (getHoverColor ());
    5.  
    6. // ...probably more drawing code here..
    7.  
    8. if (mMouseOverCloseButtonFlag == true)
    9. {
    10. painter.save ();
    11. painter.setPen (Qt::transparent);
    12. painter.setBrush (brushHover);
    13. painter.drawRect (width () - s_iButtonWidth - 1, 1, s_iButtonWidth, s_iButtonWidth - 1);
    14. painter.restore ();
    15. }
    16.  
    17. // ...probably more drawing code here too..
    18. }
    To copy to clipboard, switch view to plain text mode 

    Ugly and unpolished code, but it shows the way to do it. This way your custom widget can be style-aware and you can use as many custom style fields your heart desires.

    Hope I've been useful to someone :-)

    Cheers!

Similar Threads

  1. Replies: 0
    Last Post: 19th March 2012, 19:09
  2. How to apply style for widget over application style
    By muthu-ms in forum Qt Programming
    Replies: 5
    Last Post: 21st October 2011, 08:16
  3. custom widget with the windows7 style titlebar??
    By pirlogy in forum Qt Programming
    Replies: 1
    Last Post: 21st May 2011, 00:30
  4. Replies: 0
    Last Post: 4th November 2010, 14:51
  5. Style Sheet for custom widget
    By 1111 in forum Qt Programming
    Replies: 3
    Last Post: 31st August 2010, 12:52

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.