Search code examples
user-interfacepyqt5

PyQt5 with QSpliter and multi-level tabs


I'm struggling with proper layout of tabs in my GUI. As you can see, the QFrame in righthand side of splitter is not spanning the whole window - I suspect it is happening because it is not added to any layout that span whole tab, but I'm unable to figure out how to do that and messing around for a while. Can somebody help me?

from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QSplitter, QTabWidget, QPlainTextEdit, \
    QHBoxLayout, QFrame, QTableWidget
from PyQt5.QtGui import QCloseEvent
from PyQt5.QtCore import Qt
import sys


class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle('title')
        self.resize(1400, 800)

        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        main_layout = QVBoxLayout(central_widget)

        splitter = QSplitter()
        main_layout.addWidget(splitter)

        # Left tabs for plots
        left_tab_widget = QTabWidget()
        self.left_tab_1 = QWidget()
        self.left_tab_2 = QWidget()
        self.left_tab_3 = QWidget()
        left_tab_widget.addTab(self.left_tab_1, "left 1")
        left_tab_widget.addTab(self.left_tab_2, "left 2")
        left_tab_widget.addTab(self.left_tab_3, "left 3")

        # Right tabs for GUI
        # main tabs
        right_tab_widget = QTabWidget()
        self.right_tab_1 = QWidget()
        self.right_tab_2 = QWidget()


        # child tabs
        right_tab_2_children = QTabWidget()
        self.right_tab_2_1 = QWidget()
        self.right_tab_2_2 = StructureVariableControls()

        right_tab_2_children.addTab(self.right_tab_2_1, "right 2_1")
        right_tab_2_children.addTab(self.right_tab_2_2, "right 2_2")

        right_tab_widget.addTab(self.right_tab_1, "right 1")
        right_tab_widget.addTab(right_tab_2_children, "right 2")

        splitter.addWidget(left_tab_widget)
        splitter.addWidget(right_tab_widget)

        right_tab_widget.setCurrentIndex(1)
        right_tab_2_children.setCurrentIndex(1)
        
        
class StructureVariableControls(QWidget):
    def __init__(self):
        super().__init__()
        self.layout = QVBoxLayout()
        self.layout.setAlignment(Qt.AlignTop)

        self.frame = QFrame(self)

        self.frame.setFrameShape(QFrame.StyledPanel)
        self.frame.setFrameShadow(QFrame.Raised)
        self.frame.setStyleSheet("background-color: rgb(200, 200, 200);")
        self.frame.setLineWidth(10)

        self.frame_layout = QVBoxLayout(self.frame)
        self.table_widget = QTableWidget()
        self.frame_layout.addWidget(self.table_widget)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

Solution

  • If you add "self" in QVBoxLayout and add frame to the layout it solves the problem. StructureVariableControls class should look like this:

    class StructureVariableControls(QWidget):
        def __init__(self):
            super().__init__()
            self.layout = QVBoxLayout(self)
            self.layout.setAlignment(Qt.AlignTop)
    
            self.frame = QFrame(self)
    
            self.frame.setFrameShape(QFrame.StyledPanel)
            self.frame.setFrameShadow(QFrame.Raised)
            self.frame.setStyleSheet("background-color: rgb(200, 200, 200);")
            self.frame.setLineWidth(10)
    
            self.frame_layout = QVBoxLayout(self.frame)
            self.table_widget = QTableWidget()
            self.frame_layout.addWidget(self.table_widget)
    
            self.layout.addWidget(self.frame)
    

    I hope this solves problem