PDA

View Full Version : [Qt4/X11] Drawing theme-specific focus marker (rectangle) on custom widget



gargoylle_ltk
2nd November 2009, 22:43
I wrote a custom widget which groups other widgets under expandable categories. Each category is denoted by a 'handle' widget which can be clicked or activated with the 'space' key in order to expand/collapse the associated widget. Handles are implemented in a class derived from QWidget with the following custom paintEvent():

void CWidgetHandle::paintEvent( QPaintEvent *event )
{
QPainter painter( this );
QImage *icon = ( m_target->isVisible() ? &m_icnCollapse : &m_icnExpand );

painter.eraseRect( event->rect() );
QSize ts = painter.fontMetrics().size( Qt::TextShowMnemonic, m_label, 0, NULL );
painter.drawImage( 7, ( size().height() - icon->size().height() ) / 2, *icon );
painter.drawText( QRect( QPoint( icon->size().width() + 10, ( size().height() - ts.height() ) / 2 ), ts ), m_label );

if ( hasFocus() ) {
QVector<qreal> dashes;
QPen pen;

dashes << 1 << 2 << 1 << 2 << 1 << 2 << 1 << 2 << 1 << 2;

pen.setColor( painter.pen().color() );
pen.setStyle( Qt::CustomDashLine );
pen.setDashPattern( dashes );
pen.setCapStyle( Qt::RoundCap );
painter.setPen( pen );
painter.drawRect( 2, 2, size().width() - 5, size().height() - 5 );
}
}
The question I have is about proper drawing in the case of focused handles. Obviously the code as it stands now will only generate good looking visuals in only some cases. For exemplification this is how the test application looks while running under Gnome:

Handle focused (with an 'embedded' QPushButton)
3805

Button focused
3804

Is there any way I can get Qt to draw that theme-specific focus rectangle for my custom widget ?

gargoylle_ltk
3rd November 2009, 23:26
Since my last post I have found a (partial) solution to the problem. I've modified the paintEvent() posted above to this:

void CWidgetHandle::paintEvent( QPaintEvent *event )
{
QStylePainter painter( this );
QImage *icon = ( m_target->isVisible() ? &m_icnCollapse : &m_icnExpand );

painter.eraseRect( event->rect() );
QSize ts = painter.fontMetrics().size( Qt::TextShowMnemonic, m_label, 0, NULL );
painter.drawImage( 7, ( size().height() - icon->size().height() ) / 2, *icon );
painter.drawText( QRect( QPoint( icon->size().width() + 10, ( size().height() - ts.height() ) / 2 ), ts ), m_label );

if ( hasFocus() ) {
QStyleOption bopt;

bopt.initFrom( this );
bopt.rect = QRect( QPoint( 2, 2 ), QSize( size().width() - 4, size().height() - 4 ) );

painter.drawPrimitive( QStyle::PE_FrameFocusRect, bopt );
}
}
This now generates the expected output under Gnome but under Kde nothing (as in no focus frame) is displayed. If anyone has any suggestion don't be shy :)