Dottorhouse
28th February 2017, 09:43
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:
CustomTitlebar
{
application-icon: url(:/icons/appicon.png);
background-color: #999999;
background-color-hover: #DDDDDD;
minimize-icon: url(:/icons/minimize.png);
maximize-icon: url(:/icons/maximize.png);
close-icon: url(:/icons/close.png);
text-color: #000000;
}
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:
CustomTitlebar
{
background-color: #999999;
color: #000000;
}
On my CustomTitlebar paintEvent function I'm using the styles drawing primitives:
void CustomTitleBar::paintEvent ( QPaintEvent *event )
{
QPainter painter (this);
QStyleOption styleOption;
styleOption.init (this);
style ()->drawPrimitive (QStyle::PE_Widget, &styleOption, &painter, this);
style ()->drawItemText (&painter, rect (), Qt::AlignCenter, styleOption.palette, true, mTitle);
if (mMouseOverCloseButtonFlag == true)
{
painter.save ();
painter.setPen (Qt::transparent);
painter.setBrush (mBrushHover);
painter.drawRect (width () - s_iButtonWidth - 1, 1, s_iButtonWidth, s_iButtonWidth - 1);
painter.restore ();
}
if (mMouseOverMinimizeButtonFlag == true)
{
painter.save ();
painter.setPen (Qt::transparent);
painter.setBrush (mBrushHover);
painter.drawRect (width () - s_iButtonWidth * 2 - 1, 1, s_iButtonWidth, s_iButtonWidth - 1);
painter.restore ();
}
style ()->drawItemText (&painter, QRect (width () - s_iButtonWidth * 2, 0, s_iButtonWidth, s_iButtonWidth), Qt::AlignCenter, styleOption.palette, true, "_");
style ()->drawItemText (&painter, QRect (width () - s_iButtonWidth, 0, s_iButtonWidth, s_iButtonWidth), Qt::AlignCenter, styleOption.palette, true, "X");
}
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:
void CustomTitleBar::paintEvent ( QPaintEvent *event )
{
QPainter painter (this);
QStyleOption styleOption;
styleOption.init (this);
style ()->drawPrimitive (QStyle::PE_Widget, &styleOption, &painter, this);
style ()->drawItemText (&painter, rect (), Qt::AlignCenter, styleOption.palette, true, mTitle);
QRect rect1 (width () - s_iButtonWidth - 1, 1, s_iButtonWidth, s_iButtonWidth - 1);
QRect rect2 (width () - s_iButtonWidth - 1, 1, s_iButtonWidth, s_iButtonWidth - 1);
if (mMouseOverCloseButtonFlag == true)
{
style ()->drawRect (&painter, rect1, "CustomTitlebar::background-color-hover");
}
if (mMouseOverMinimizeButtonFlag == true)
{
style ()->drawRect (&painter, rect2, "CustomTitlebar::background-color-hover");
}
style ()->drawItemPixmap (&painter, rect1, Qt::AlignRight, "CustomTitlebar::close-icon");
style ()->drawItemPixmap (&painter, rect2, Qt::AlignRight, "CustomTitlebar::minimize-icon");
}
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!
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:
CustomTitlebar
{
application-icon: url(:/icons/appicon.png);
background-color: #999999;
background-color-hover: #DDDDDD;
minimize-icon: url(:/icons/minimize.png);
maximize-icon: url(:/icons/maximize.png);
close-icon: url(:/icons/close.png);
text-color: #000000;
}
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:
CustomTitlebar
{
background-color: #999999;
color: #000000;
}
On my CustomTitlebar paintEvent function I'm using the styles drawing primitives:
void CustomTitleBar::paintEvent ( QPaintEvent *event )
{
QPainter painter (this);
QStyleOption styleOption;
styleOption.init (this);
style ()->drawPrimitive (QStyle::PE_Widget, &styleOption, &painter, this);
style ()->drawItemText (&painter, rect (), Qt::AlignCenter, styleOption.palette, true, mTitle);
if (mMouseOverCloseButtonFlag == true)
{
painter.save ();
painter.setPen (Qt::transparent);
painter.setBrush (mBrushHover);
painter.drawRect (width () - s_iButtonWidth - 1, 1, s_iButtonWidth, s_iButtonWidth - 1);
painter.restore ();
}
if (mMouseOverMinimizeButtonFlag == true)
{
painter.save ();
painter.setPen (Qt::transparent);
painter.setBrush (mBrushHover);
painter.drawRect (width () - s_iButtonWidth * 2 - 1, 1, s_iButtonWidth, s_iButtonWidth - 1);
painter.restore ();
}
style ()->drawItemText (&painter, QRect (width () - s_iButtonWidth * 2, 0, s_iButtonWidth, s_iButtonWidth), Qt::AlignCenter, styleOption.palette, true, "_");
style ()->drawItemText (&painter, QRect (width () - s_iButtonWidth, 0, s_iButtonWidth, s_iButtonWidth), Qt::AlignCenter, styleOption.palette, true, "X");
}
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:
void CustomTitleBar::paintEvent ( QPaintEvent *event )
{
QPainter painter (this);
QStyleOption styleOption;
styleOption.init (this);
style ()->drawPrimitive (QStyle::PE_Widget, &styleOption, &painter, this);
style ()->drawItemText (&painter, rect (), Qt::AlignCenter, styleOption.palette, true, mTitle);
QRect rect1 (width () - s_iButtonWidth - 1, 1, s_iButtonWidth, s_iButtonWidth - 1);
QRect rect2 (width () - s_iButtonWidth - 1, 1, s_iButtonWidth, s_iButtonWidth - 1);
if (mMouseOverCloseButtonFlag == true)
{
style ()->drawRect (&painter, rect1, "CustomTitlebar::background-color-hover");
}
if (mMouseOverMinimizeButtonFlag == true)
{
style ()->drawRect (&painter, rect2, "CustomTitlebar::background-color-hover");
}
style ()->drawItemPixmap (&painter, rect1, Qt::AlignRight, "CustomTitlebar::close-icon");
style ()->drawItemPixmap (&painter, rect2, Qt::AlignRight, "CustomTitlebar::minimize-icon");
}
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!