Search code examples
pythonpyqtpyqt5qtabwidget

PyQt Options for each Tab Widget


I have a tab widget that contains table widgets for each tab, and I also have a dock widget with options. One of the options is the column count, and I want to change it as soon as the column count spin box value changes. But when switching to a different tab, I'd like the spin box value (and all other options) to reset / switch to that specific tab's settings.

My question is how to best do this and still have the options as a dock widget. I could store all settings as variables for each tab widget and then change the value each time a new tab is opened, I guess, but maybe there is a better solution.

from PyQt5 import QtWidgets, QtCore

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent = None):
        super(MainWindow, self).__init__()
        self.__setup__()

    def __setup__(self):
        self.resize(400, 400)
        tabWidget = TabWidget(self)
        self.setCentralWidget(tabWidget)

        options = Options(self)
        optionsDock = QtWidgets.QDockWidget()
        optionsDock.setWidget(options)
        optionsDock.setWindowTitle("Options")
        self.addDockWidget(QtCore.Qt.TopDockWidgetArea, optionsDock)

        options.spinBox_columns.valueChanged.connect(lambda: tabWidget.tabWidget.currentWidget().
                                                     setColumnCount(options.spinBox_columns.value()))

class Options(QtWidgets.QWidget):
    def __init__(self, parent):
        super(Options, self).__init__(parent)
        self.__setup__()

    def __setup__(self):
        self.spinBox_columns = QtWidgets.QSpinBox()
        self.spinBox_columns.setValue(1)
        self.spinBox_columns.setMinimum(1)

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.spinBox_columns)
        self.setLayout(layout)

class TabWidget(QtWidgets.QWidget):
    def __init__(self, parent):
        super(TabWidget, self).__init__(parent)
        self.__setup__()

    def __setup__(self):
        self.tabWidget = QtWidgets.QTabWidget()

        for i in range(3):
            widget = QtWidgets.QTableWidget()
            widget.setColumnCount(1)
            widget.setRowCount(3)
            self.tabWidget.addTab(widget, "Column " + str(i))

        layout = QtWidgets.QVBoxLayout()
        layout.addWidget(self.tabWidget)
        self.setLayout(layout)

def main():
    import sys
    app = QtWidgets.QApplication(sys.argv) 
    window = MainWindow() 
    window.show() 
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

Solution

  • You have to connect the currentChanged signal provided by the index of the tab, then use the widget() method to obtain the index associated with that index, then access its QTabWidget and obtain the number of columns using it to place the value to the QSpinBox.

    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self, parent=None):
            super(MainWindow, self).__init__(parent)
            self.__setup__()
    
        def __setup__(self):
            self.resize(400, 400)
            tabWidget = TabWidget(self)
            self.setCentralWidget(tabWidget)
    
            options = Options(self)
            optionsDock = QtWidgets.QDockWidget()
            optionsDock.setWidget(options)
            optionsDock.setWindowTitle("Options")
            self.addDockWidget(QtCore.Qt.TopDockWidgetArea, optionsDock)
    
            tabWidget.tabWidget.currentChanged.connect(lambda index: options.spinBox_columns.
                                                       setValue(tabWidget.tabWidget.widget(index).columnCount()))
    
            options.spinBox_columns.valueChanged.connect(lambda value: tabWidget.tabWidget.currentWidget().
                                                         setColumnCount(value))