Horst Walter
Horst Walter

Reputation: 14081

Hide label text for Qt tabs without setting text to empty string

I need a QTabWidget with icons only:

How can I hide the label text of a tab in Qt? I cannot set the text to an empty string (""), as I am using docked widgets ( QDockWidget ) and the label text is set automatically (and I need it if the widget is floating).

But in tabbed mode I just want to display the icons (of the tabs). Possible approaches:

  1. Font size to 0?
  2. I need to create my own bar class and override the paint event as here

Anything easier / cleaner?

--- Edit ---

Ok, the "set window title to empty string, and reset it the original text" approach works. I am using the topLevelChanged signal for this. However, it has some drawbacks, as the empty text still occupies some space. Another issue, with the text the tooltip is gone, and I cannot set it back.

Still some space consumed

What I am currently trying is something in-between the "text empty" and Prasad Silva's approach. I try to identify the text label inside the tab and set its size to 0, then reset it. It's slightly different, but would keep the text intact.

Btw, I see a line on top of my tabs, any idea what this is (where it comes from)? Edit: There seems to be no "easy way" (style sheet, attribute) for this, see Hiding bottom line in QTabBar

Maybe I will create the whole tab bar on my own, as the automatically generated stuff is just too hard to handle (agree with PS on this).

Upvotes: 5

Views: 2680

Answers (4)

dukeeloo
dukeeloo

Reputation: 163

Since this was still one of the first things I found when looking for something like this I thought I post my solution here. I basically play with font size and margins to make it look like the labels are gone even if they are still there. Since it can be hard to see which tab is selected if there are only icons I still show the text of the selected tab.

Example with labels, icons, or both

import sys
from PyQt6.QtWidgets import QApplication,QMainWindow,QDockWidget,QToolBar,QPushButton,QVBoxLayout,QWidget,QTabBar
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QIcon

class Foo(QMainWindow):

    def __init__(self):
        super().__init__()        
        central_widget = QWidget(self)
        self.setCentralWidget(central_widget)
        lay = QVBoxLayout(central_widget) 
        
        self.setStyleSheet("""QTabBar::tab{margin:0px 0px 2px 0px; padding:4px; border-width:0px; }
        QTabBar::tab:selected{margin:0px 0px 0px 0px; padding:4px; border-bottom-width:2px; color:#8ab4f7; border-bottom-color:#8ab4f7; border-style:solid;}""")
        
        self.docks = []
        self.docks.append(QDockWidget('dock0'))
        self.addDockWidget(Qt.DockWidgetArea.BottomDockWidgetArea, self.docks[0])
        for i in range(4):
            self.docks.append(QDockWidget(f'dock{i+1}'))
            self.tabifyDockWidget(self.docks[0], self.docks[i+1])        
        
        button = QPushButton('Use Labels')
        button.clicked.connect(lambda: self.updateTabs('labels'))
        lay.addWidget(button)
        button = QPushButton('Use Icons')
        button.clicked.connect(lambda: self.updateTabs('icons'))
        lay.addWidget(button)
        button = QPushButton('Use Icons and Labels')
        button.clicked.connect(lambda: self.updateTabs('both'))
        lay.addWidget(button)
        
    def updateTabs(self, mode):
        tabBars = self.findChildren(QTabBar)
        if tabBars:
            for tabBar in tabBars:
                tabBar.setStyleSheet('QTabBar::tab {font-size: 1px; margin-right: -18px; color: transparent} QTabBar::tab:selected {font-size: 12px;margin-right: 0px; color:#8ab4f7;}' if mode == 'icons' else '')
                for i in range(tabBar.count()):
                    tabBar.setTabIcon(i, QIcon() if mode == 'labels' else self.getIcon(tabBar.tabText(i)))
        
    def getIcon(self, text):
        # replace with your icons. Here icon0.png, icon1.png, ...
        return QIcon(text)        
            
if __name__ == '__main__':
    app = QApplication(sys.argv)
    mainWindow = Foo()
    mainWindow.show()
    sys.exit(app.exec())

Upvotes: 0

Prasad Silva
Prasad Silva

Reputation: 1042

The way I solved something like was to create a QDockWidget subclass that installed a QWidget subclass as the titlebar (via setTitleBarWidget). This gave me control over showing/hiding the text in the titlebar when the dock widget fires topLevelChanged, dockLocationChanged and visiblityChanged.

This is really a big hack to get around the fact that Qt has refused to expose a public API for the docking system. We have since moved on to a custom docking implementation due to these limitations.

Upvotes: 3

László Papp
László Papp

Reputation: 53175

If you do not want to see the text, you can set it to an empty text after saving the current text, and when you want to see it again, restore it from the stored variable.

I do not think there is anything in the API for this not so common case, which means you will need to do it yourself.

Now, you could claim that it is tedious to do for many widgets, but on the other hand, you could write a simple hash define or inline function to do this repetitive work for you, which would only result a one-liner call, basically, which you would need to use anyway when changing the state.

Upvotes: 1

Silicomancer
Silicomancer

Reputation: 9186

This can not be done easily. Use empty text.

Upvotes: 3

Related Questions