[PyKDE] PyQt: Better highlighting in QTabWidgets (improves eric3 and other Qt3.x apps)

Thilo Ernst te0006 at web.de
Wed Dec 14 14:17:45 GMT 2005


in our own simulation-related PyQt app as well as in eric3 we found that
the current tab in a QTabWidget is visually hard to recognize: apart
form the decoration lines and a barely visible increase in the height of the
tab's background it looks just like the  other tabs. As a consequence,
the user is sometimes mistaken about which tab is active, types into the
wrong page, etc.

We thus went digging for ways to have the current tab highlighted in some
way - which turned out to be surprisingly difficult. The only  feasible way
involved subclassing QTabBar and overriding its paintLabel() method.
However this had to be combined with a rather nonintuitive way of detecting
the current tab, otherwise strange rendering problems (some tabs not being
painted at all) would occur when the app used more than one QTabWidget
instance. Also, among the many conceivable ways to actually do the
highlighting (foreground or background color, font weight etc.) , only 
font().setUnderline() proved to be both working in the first place and 
to not
result in unwanted side effects (such as font metrics problems).

The code snippet below is the result of our efforts: a working QTabWidget
drop-in replacement class which renders the current tab underlined.

To have this widget work with Qt-Designer-generated code without the need
to touch said generated code, we devised only a rather dirty solution:
monkey-patching the qt module such that the 'QTabWidget' entry in the 
dictionary refers to our new class (cf. last code line). If anybody 
knows a cleaner
approach, please let the list know.

Feel free to use this code snippet in your own application. We would be
delighted to see it ending up e.g. in a forthcoming version of eric3. 
(Hint: inserting it after line 15 of eric-3.8.0/eric/eric3.py suffices 
although this admittedly won't yield any style points :-)

Best regards,

Thilo Ernst, Fraunhofer FIRST

--- snip ---

import qt

class HighlightedTabBar(qt.QTabBar):
    """a tab bar where the label of the selected tab is painted 
    def paintLabel(self, painter, rect, tab, has_focus):
        # don't use QTabBar.currentTab() - here be dragons
        selected= (self.tabAt(self.indexOf(self.currentTab()))==tab)
        if selected:
              # options for style emphasis: foreground/background colors 
don't work.
              # Bold works but disturbs the font metrics. Underline Just 
        qt.QTabBar.paintLabel(self, painter, rect, tab, has_focus)
        if selected:


class HighlightedTabWidget(QTabWidget_orig):
    """A QTabWidget equivalent which uses our HighlightedTabBar"""
    def __init__(self, parent, *args):
        QTabWidget_orig.__init__(self, parent, *args)
qt.QTabWidget=HighlightedTabWidget # monkey-patch the qt module to use 
this implementation

-- snip ---

More information about the PyQt mailing list