Bebe
24th June 2013, 16:49
I have created a custom QPushButton so if a button has both an icon and text I can place draw the text below the button image. My button image has 3D borders so am using stylesheets to provide non-scaling borders.
The the button looks correct in all the states but selected or pressed, so I know it understands the state changes and is getting the images from the style sheet. My first guess was that the style sheet image was incorrect.
When I comment out the paintEvent() function all the states draw properly even though the text is drawn on the button. So I know the button is getting the mouse event, the style sheet images are correct, the button is getting the press event, and the style sheet can correctly be used for all the state changes. What in this paintEvent() could possibly prevent the button from drawing itself selected if it will draw itself in the hover state?
Here is the style sheet code:
MyButton{
outline: none; /* remove focus rectangle */
text-overflow: ellipsis;
border-image: url(:/images/Resources/Images/Active.png) 9;
border: 9px transparent;
}
MyButton:selected {
border-image: url(:/images/Resources/Images/Selected.png) 9;
}
MyButton:focus {
border-image: url(:/images/Resources/Images/Focus.png) 9;
}
MyButton:hover {
border-image: url(:/images/Resources/Images/Focus.png) 9;
}
MyButton:pressed {
border-image: url(:/images/Resources/Images/Selected.png) 9;
}
void MyPushButton::paintEvent ( QPaintEvent * pEvent )
{
QStyleOption opt;
QPainter p(this);
QRect iconRect;
QRect textRect;
QRect btnRect = this->rect();
opt.init(this);
if (!this->icon().isNull() && !this->text().isEmpty()) {
//decrease the height of the drawing area so it doesn't cover the text
opt.rect.adjust(0,0,0,-(fontMetrics().height() * 2));
}
//draw the backround
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
/*
Tried adding this and removing the "outline: none;" from the style sheet with no affect
I added this with the conditional to verify that it was getting focus…
//draw the focus/selection rect
if (opt.state & QStyle::State_HasFocus) {
QStyleOptionFocusRect focusOpt;
focusOpt.QStyleOption::operator=(opt);
//focusOpt.state | QStyle::State_FocusAtBorder; // tried with and without – no change
style()->drawPrimitive(QStyle::PE_FrameFocusRect, &focusOpt, &p, this);
}
*/
if (!this->icon().isNull())
{
iconRect.setRect(10,10, opt.rect.width()-30, opt.rect.height()-20);
//Draw the icon
style()->drawItemPixmap(&p, iconRect, Qt::AlignLeft | Qt::AlignVCenter,
this->icon().pixmap(iconRect.size()));
if (!this->text().isEmpty()) {
opt.rect.adjust(0,0,0,fontMetrics().height() * 2);
// This button has an icon and text. The text should be drawn below
textRect.setRect(btnRect.x(),
45,
btnRect.width(),
fontMetrics().height() * 2);
style()->drawItemText(&p, textRect, Qt::AlignCenter, (this->palette()),
true, this->text(), QPalette::ButtonText );
}
} else {
if (!this->text().isEmpty()) {
// this button has text but no icon
// Draw the text centered on the button
style()->drawItemText(&p, this->rect(), Qt::AlignCenter, (this->palette()),
true, this->text());
}
}
}
The the button looks correct in all the states but selected or pressed, so I know it understands the state changes and is getting the images from the style sheet. My first guess was that the style sheet image was incorrect.
When I comment out the paintEvent() function all the states draw properly even though the text is drawn on the button. So I know the button is getting the mouse event, the style sheet images are correct, the button is getting the press event, and the style sheet can correctly be used for all the state changes. What in this paintEvent() could possibly prevent the button from drawing itself selected if it will draw itself in the hover state?
Here is the style sheet code:
MyButton{
outline: none; /* remove focus rectangle */
text-overflow: ellipsis;
border-image: url(:/images/Resources/Images/Active.png) 9;
border: 9px transparent;
}
MyButton:selected {
border-image: url(:/images/Resources/Images/Selected.png) 9;
}
MyButton:focus {
border-image: url(:/images/Resources/Images/Focus.png) 9;
}
MyButton:hover {
border-image: url(:/images/Resources/Images/Focus.png) 9;
}
MyButton:pressed {
border-image: url(:/images/Resources/Images/Selected.png) 9;
}
void MyPushButton::paintEvent ( QPaintEvent * pEvent )
{
QStyleOption opt;
QPainter p(this);
QRect iconRect;
QRect textRect;
QRect btnRect = this->rect();
opt.init(this);
if (!this->icon().isNull() && !this->text().isEmpty()) {
//decrease the height of the drawing area so it doesn't cover the text
opt.rect.adjust(0,0,0,-(fontMetrics().height() * 2));
}
//draw the backround
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
/*
Tried adding this and removing the "outline: none;" from the style sheet with no affect
I added this with the conditional to verify that it was getting focus…
//draw the focus/selection rect
if (opt.state & QStyle::State_HasFocus) {
QStyleOptionFocusRect focusOpt;
focusOpt.QStyleOption::operator=(opt);
//focusOpt.state | QStyle::State_FocusAtBorder; // tried with and without – no change
style()->drawPrimitive(QStyle::PE_FrameFocusRect, &focusOpt, &p, this);
}
*/
if (!this->icon().isNull())
{
iconRect.setRect(10,10, opt.rect.width()-30, opt.rect.height()-20);
//Draw the icon
style()->drawItemPixmap(&p, iconRect, Qt::AlignLeft | Qt::AlignVCenter,
this->icon().pixmap(iconRect.size()));
if (!this->text().isEmpty()) {
opt.rect.adjust(0,0,0,fontMetrics().height() * 2);
// This button has an icon and text. The text should be drawn below
textRect.setRect(btnRect.x(),
45,
btnRect.width(),
fontMetrics().height() * 2);
style()->drawItemText(&p, textRect, Qt::AlignCenter, (this->palette()),
true, this->text(), QPalette::ButtonText );
}
} else {
if (!this->text().isEmpty()) {
// this button has text but no icon
// Draw the text centered on the button
style()->drawItemText(&p, this->rect(), Qt::AlignCenter, (this->palette()),
true, this->text());
}
}
}