2

I am trying to check existing tabs in a QTabBar against the list of items within a QMenu. And if the existing tabs contains item(s) that are not found in the QMenu, that said tab is to be highlighted in red.

Initially I was using the tabTextColor however it does not seems to be changing the text color. Then as I googled around, some were saying to use setStylesheet instead and hence I decided to change the background color instead of the text color that I was initially going for.

Even so, I am having issues in 'retaining' the red color/ setting color to a particular tab. In my following code, if I do the following:

  1. Populate 3 tabs eg. (A, B, C), contents read from a text file
  2. Remove B from text file
  3. Click on the add button, this will highlight the B tab to Red
  4. If I navigate to tab C, tab C will be colored red and the initial highlight B will be reverted back to the original color. And for any tabs I am selecting now, it will be highlighted in red.

Appreciate for any insights on this.

class MyWin(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(MyWin, self).__init__()
        central_widget = QtGui.QWidget()
        self.setCentralWidget(central_widget)
        vlay = QtGui.QVBoxLayout(central_widget)
        hlay = QtGui.QHBoxLayout()
        vlay.addLayout(hlay)
        vlay.addStretch()

        self.add_button = QtGui.QToolButton()
        self.tab_bar = QtGui.QTabBar(self)
        self.add_button.setIcon(QtGui.QIcon('add.png'))

        self.qmenu = QtGui.QMenu(self.add_button)
        self.add_button.setMenu(self.qmenu)
        self.add_button.setPopupMode(QtGui.QToolButton.InstantPopup)

        self.qmenu.aboutToShow.connect(self.set_menu)

        self.tab_bar.setTabButton(
            0,
            QtGui.QTabBar.ButtonPosition.RightSide,
            self.add_button
        )
        hlay.addWidget(self.add_button)
        hlay.addWidget(self.tab_bar)

    @QtCore.pyqt.Slot()
    def set_menu(self):
        with open('/Desktop/item_file.txt') as f:
            menu_options = f.read().splitlines()
        self.qmenu.clear()

        self.tabs_precheck()

        for opt in menu_options:
            self.qmenu.addAction(opt, partial(self.set_new_tab, opt))

    def get_all_tabs(self):
        all_existing_tabs = {}
        for index in range(self.tab_bar.count()):
            all_existing_tabs[index] = self.tab_bar.tabText(index)

        return all_existing_tabs

    def set_new_tab(self, opt):
        all_tabs = self.get_all_tabs()

        if not opt in all_tabs.values():
            self.tab_bar.addTab(opt)

    def tabs_precheck(self):
        # Get the tabs that are already populated
        before_tabs = {}
        for index in range(self.tab_bar.count()):
            before_tabs[self.tab_bar.tabText(index)] = index


        # Get the items in qmenu items
        with open('/Desktop/item_file.txt') as f:
           qmenu_items = f.read().splitlines()


        # Get the difference between the 2
        difference = list(set(before_tabs.keys()) - set(qmenu_items))

        for diff in difference:
            # Get the 'before' index
            index_value = before_tabs.get(diff)
            # Set that particular tab background color to 'RED'
            self.tab_bar.setCurentIndex(index_value)
            self.tab_bar.setStyleSheet('''
                QTabBar::tab {background-color: red;}
                '''
            )


if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    w = MyWin()
    w.show()
    sys.exit(app.exec_())
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Teh Ki
  • 455
  • 1
  • 3
  • 14
  • From what I understand if you have n tabs and if one does not match the .txt list then it should have a red background color, am I correct? – eyllanesc Jan 07 '19 at 20:46
  • I see that in PyQt4 it is only possible to change the color of the text, not the background color. – eyllanesc Jan 07 '19 at 21:13
  • Hi, yes, it should appear red. Surprisingly for me, when I tried to change the color of the text, it fails whereas it works if I am doing for the background color – Teh Ki Jan 07 '19 at 22:26
  • QSS does not serve to apply the style to each tab, so it fails, instead with setTabTextColor if you can change the color for each index. Would it be nice if I point out the solution that only changes the color of the text? – eyllanesc Jan 07 '19 at 22:30
  • @eyllanesc Please do point out the solution if you could, greatly appreciate it :) – Teh Ki Jan 07 '19 at 22:37

1 Answers1

1

You have to use setTabTextColor() but I see that it is failing because you are applying a wrong logic, the solution is:

def tabs_precheck(self):
    with open('/Desktop/item_file.txt') as f:
       qmenu_items = f.read().splitlines()
       if qmenu_items:
            for index in range(self.tab_bar.count()):
                text = self.tab_bar.tabText(index)
                color = QtCore.Qt.black if text in qmenu_items else QtCore.Qt.red
                self.tab_bar.setTabTextColor(index, color)
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • It does not really work. It is able to return me `QtCore.Qt.GlobalColor.red` that the color for the said tab has changed, but in my GUI, the text color still remains the same - white color in this case, instead of the red I am seeing – Teh Ki Jan 07 '19 at 23:24
  • @TehKi White color by default ?, the color of the text by default is black, the code you have shown is an MCVE ?, I think there is another part of your code that is causing conflicts, try with: `app.setStyle("fusion")` – eyllanesc Jan 07 '19 at 23:30