1

I've a GUI (written in PyQt) with three tabs, each a QtGui.QMainWindow class. The whole GUI is defined by a .ui file. That seems to be the main difference between the similar questions on SO (links in next paragraph) where people are looking to hide a QMainWindow object. More specifically, that I'm trying to hide a QMainWindow object that's part of (not the whole) Gui element.

The main window and its tabs look like this:

enter image description here

Depending on a setting in my config file, I want to either leave TEST visible, or hide it from the user. I've checked both the PyQT Docs (ie removeDockWidget()?) and there are two similar SO queries (Link One and link Two), and a SO Question suggesting layouts/setVisible..

But I can't get it right. If I use .hide() or .setVisible(False) then nothing seems to change. If I set .setVisible(True) then an additional, miniature window appears on startup, with the name of my main class.

The structure of my code is:

My entry/main class:

class Gui:
    def __init__(self):
        # Create the main window GUI and show it
        self.mainWindow= GuiMainWindow(self)
        self.mainWindow.show()
    <...>        

def main():
    app = QtGui.QApplication(sys.argv)  
    myGui = Gui(app)
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

GuiMainWindow contain the three tabs:

class GuiMainWindow(QtGui.QMainWindow):
    def __init__(self, appMain):
        QtGui.QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        # Create helper objects to manage main window tabs
        self.daqTab = GuiMainDaqTab(appMain, self)
        self.pwrTab = GuiMainPowerTab(appMain, self)
        self.testTab = GuiMainTestTab(appMain, self)

        self.testTab.hideMe()

Finally, the TEST tab is what I want to hide/show:

class GuiMainTestTab(QtGui.QMainWindow):
    def __init__(self, appMain, mainWindow):
        super(GuiMainTestTab, self).__init__()
        self.appMain = appMain
        self.mainWindow = mainWindow
        self.ui = mainWindow.ui
        <...>

    def hideMe(self):  
        self.close()
    #   self.hide()             # Also tried hide()
    #   self.setVisible(False)  # ..Or setVisible()

--- Edit to assist the answer / my match comment to answer below ---

So, the class GuiMainTestTab accesses the contents of the ui file through its member self.ui. Digging through the ui file I found that testTab is its name of the Test tab in the ui file (as opposed to testTab in GuiMainWindow..!). It's attached to a QTabWidget called verticalTabWidget. So to programmatically find Test tab's index, and remove it:

        testIdx = self.ui.verticalTabWidget.indexOf(self.ui.testTab)
        self.ui.verticalTabWidget.removeTab(testIdx)
PhilPhil
  • 173
  • 4
  • 18

1 Answers1

2

QWidget-based actions like close(), hide(), setVisible(True) are not effecting your QTabWidget-container, just the containing page (tab). Since show, hide and other Access-functions for the visibility-property are also used by the container, your changes are overwriten later.

You can see this by calling testTab.show() while an other Tab is active.


to hide the Tab from the user, you can either:

here is a minimal working example using the second approach:

def main ( ) :
    from PyQt5.QtWidgets import QApplication
    app = QApplication( [] )
    window = Test_Dialog()
    window.show()
    exit( app.exec() )

class Ui_Dialog( object ) :
    def setupUi ( self, Dialog ) :
        from PyQt5 import QtCore, QtWidgets
        self.tabWidget = QtWidgets.QTabWidget( Dialog )
        self.tabWidget.setGeometry( QtCore.QRect( 9, 9, 181, 121 ) )
        self.tab = QtWidgets.QWidget()
        self.pushButton_remove = QtWidgets.QPushButton( "remove", self.tab )
        self.pushButton_remove.setGeometry( QtCore.QRect( 20, 10, 75, 23 ) )
        self.pushButton_add = QtWidgets.QPushButton( "add", self.tab )
        self.pushButton_add.setGeometry( QtCore.QRect( 20, 60, 75, 23 ) )
        self.tabWidget.addTab( self.tab, "Tab 1" )
        self.tab_2 = QtWidgets.QWidget()
        self.lineEdit = QtWidgets.QLineEdit( self.tab_2 )
        self.lineEdit.setGeometry( QtCore.QRect( 30, 30, 113, 20 ) )
        self.tabWidget.addTab( self.tab_2, "Tab 2" )  # remove this for approach #1

from PyQt5.QtWidgets import QDialog
class Test_Dialog( QDialog, Ui_Dialog ) :
    def __init__ ( self ) :
        QDialog.__init__( self )
        self.setupUi( self )
        self.pushButton_remove.clicked.connect( self.hideTab )
        self.pushButton_add.clicked.connect( self.showTab )
    def hideTab ( self ) :
        self.save = self.tabWidget.widget( 1 )  # save it for later
        self.tabWidget.removeTab( 1 )
    def showTab ( self ) :
        self.tabWidget.insertTab( 1, self.save, 'Tab2 is here again' ) # restore

simply use QTabWidget.remove() and QTabWidget.insert() or QTabWidget.addTab() and you even can still access erverything as normal, if you need something from the "hidden" tab.

I added a QLineEdit on "Tab 2" to show that no datas are lost when removing, just type something in there and try it.

Skandix
  • 1,916
  • 6
  • 27
  • 36
  • please note my sample is writen with `pyqt5`, but it should be completly compatible qith `pyqt4` -> simply switch the number – Skandix Feb 08 '18 at 09:35
  • Thank you, that works! - I would only add that you can programmatically find the index of the tab to be "hidden". Use `QTabWidget.indexOf(testTab)` where `testTab` is the QtGui.QWidget within the ui file. So in my (snipped) example code, `Ui_MainWindow` is the class defined in the ui file (which I excluded from my post). `testTab` would therefore be `self.ui.testTab`. – PhilPhil Feb 08 '18 at 12:00
  • That's a bit messy, I'll add a few lines to my original post to make things clearer. – PhilPhil Feb 08 '18 at 12:02