1

I want to use a QSplitter to split the MainWindow on two sides. On the left I want to have a layout containing a folder view and on the right another layout where I’ll plot some things. But I can only add Widgets on the QSplitter and the Layouts are not Widgets. The only similar questions I found were these:

http://www.qtcentre.org/threads/16856-QSplitter-multiple-layouts-how https://forum.qt.io/topic/8197/solved-qsplitter-and-qvboxlayout-problem

So, according to the above links, my plan is to create the two layouts, then add them to two QWidgets (using setLayout) and then add these QWidgets to QSplitter (using addWidget). I tried to apply that on my code but unfortunately, when I add the layout to the widget nothing shows up!

Is there another way to achieve what I want? Have I misunderstood the answers?

Here’s the code. I send you only the folder view layout in order for the code to be simpler. Also, I’m completely new to pyqt and object-oriented programming, so any commends on how to improve it are welcome!

Thanks in advance!

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *

class Window(QMainWindow):

    def __init__(self, parent=None):

        super(Window, self).__init__(parent)
        self.UI()

    def UI(self):

        self.central_widget = QStackedWidget()
        self.setCentralWidget(self.central_widget)

        self.statusBar().showMessage("Ready")

        page1 = FirstWidget(self)
        page1.visualize_btn.clicked.connect(self.P_2)
        self.central_widget.addWidget(page1)        

        self.setGeometry(10, 10, 800, 500)    #All three methods have been inherited from the QWidget class.
        self.showMaximized()
        self.setWindowTitle('PTV')
        self.setWindowIcon(QIcon('tuc_logo.png'))

    def P_2(self):

        page2 = VisualizeWidget(self)
        self.central_widget.addWidget(page2)
        self.central_widget.setCurrentWidget(page2)


class FirstWidget(QWidget):

    def __init__(self, parent=None):
        super(FirstWidget, self).__init__(parent)
        self.buttons()

    def buttons(self):

        self.btn2 = QPushButton("Visualize")
        self.buttonsLayout = QVBoxLayout() 
        self.buttonsLayout.addWidget(self.btn2)
        self.visualize_btn = self.btn2        
        self.setLayout(self.buttonsLayout)


class VisualizeWidget(QWidget):

    def __init__(self, parent=None):
        super(VisualizeWidget, self).__init__(parent)


        self.dirmodel = QFileSystemModel()        
        self.dirmodel.setFilter(QDir.NoDotAndDotDot | QDir.AllDirs)    # Don't show files, just folders

        self.folder_view = QTreeView(parent=self);
        self.folder_view.setModel(self.dirmodel)
        self.folder_view.clicked[QModelIndex].connect(self.clicked)

        self.now_layout = QVBoxLayout()
        self.now_layout.addWidget(self.folder_view)

        #self.setLayout(self.now_layout)

        #HERE is where I'm trying to add the layout to the widget. 
        self.left_widget = QWidget()
        self.left_widget.setLayout(self.now_layout)            


    def set_path(self):
        self.dirmodel.setRootPath("")

    def clicked(self, index):
        index = self.selectionModel.currentIndex()
        dir_path = self.dirmodel.filePath(index)

        self.filemodel.setRootPath(dir_path)
        self.file_view.setRootIndex(self.filemodel.index(dir_path))          

def main():
    app = QApplication(sys.argv)
    win = Window()
    win.show()
    app.exec_()

if __name__ == '__main__':
    sys.exit(main()) 
A. Dav
  • 41
  • 2
  • 5

2 Answers2

1

I haven't actually understood yet what I was doing wrong, but I'm posting a working code, in case it helps someone else in the future.

Now the two layouts are splitted with a QSplitter.

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *

class Window(QMainWindow):

    def __init__(self, parent=None):

        super(Window, self).__init__(parent)
        self.UI()

    def UI(self):

        self.central_widget = QStackedWidget()
        self.setCentralWidget(self.central_widget)

        self.statusBar().showMessage("Ready")

        page1 = FirstWidget(self)
        page1.visualize_btn.clicked.connect(self.P_2)
        self.central_widget.addWidget(page1)        

        self.setGeometry(10, 10, 800, 500)    #All three methods have been inherited from the QWidget class.
        self.showMaximized()
        self.setWindowTitle('PTV')
        self.setWindowIcon(QIcon('tuc_logo.png'))

    def P_2(self):

        page2 = VisualizeWidget(self)
        self.central_widget.addWidget(page2)
        self.central_widget.setCurrentWidget(page2)


class FirstWidget(QWidget):

    def __init__(self, parent=None):
        super(FirstWidget, self).__init__(parent)
        self.buttons()

    def buttons(self):

        self.btn2 = QPushButton("Visualize")
        self.buttonsLayout = QVBoxLayout() 
        self.buttonsLayout.addWidget(self.btn2)
        self.visualize_btn = self.btn2        
        self.setLayout(self.buttonsLayout)


class VisualizeWidget(QWidget):

    def __init__(self, parent=None):
        super(VisualizeWidget, self).__init__(parent)


        #Creation of the left layout
        self.dirmodel = QFileSystemModel()        
        self.dirmodel.setFilter(QDir.NoDotAndDotDot | QDir.AllDirs)    # Don't show files, just folders

        self.folder_view = QTreeView(parent=self);
        self.folder_view.setModel(self.dirmodel)
        self.folder_view.clicked[QModelIndex].connect(self.clicked)

        self.selectionModel = self.folder_view.selectionModel()

        self.now_layout = QVBoxLayout()
        self.now_layout.addWidget(self.folder_view)


        self.left_widget = QWidget()
        self.left_widget.setLayout(self.now_layout)


        #Creation of the right layout
        #self.right_widget = QTextEdit();

        self.btn1 = QPushButton('btn1')

        self.right_layout = QVBoxLayout()
        self.right_layout.addWidget(self.btn1)

        self.right_widget = QWidget()
        self.right_widget.setLayout(self.right_layout)




        splitter_filebrowser = QSplitter(Qt.Horizontal)
        splitter_filebrowser.addWidget(self.left_widget)
        splitter_filebrowser.addWidget(self.right_widget)
        splitter_filebrowser.setStretchFactor(1, 1)

        hbox = QHBoxLayout(self)
        hbox.addWidget(splitter_filebrowser)

        self.setLayout(hbox)



    def set_path(self):
        self.dirmodel.setRootPath("")

    def clicked(self, index):
        index = self.selectionModel.currentIndex()
        dir_path = self.dirmodel.filePath(index)

        self.filemodel.setRootPath(dir_path)
        self.file_view.setRootIndex(self.filemodel.index(dir_path))          

def main():
    app = QApplication(sys.argv)
    win = Window()
    win.show()
    app.exec_()

if __name__ == '__main__':
    sys.exit(main()) 
A. Dav
  • 41
  • 2
  • 5
0

I took the liberty of cleaning up @A.Dew's answer to its minimal generic form.

from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QSplitter, QWidget, QVBoxLayout, QMainWindow, QGridLayout, QLayout
from PyQt5.QtWidgets import QToolBar, QPushButton, QLabel


class QPanedWidget(QWidget):

    def __init__(self, first_pane: QWidget, second_pane: QWidget, orientation: Qt.Orientation = Qt.Horizontal):
        super().__init__()

        left_pane = first_pane
        right_pane = second_pane

        splitter = QSplitter(orientation)
        splitter.addWidget(left_pane)
        splitter.addWidget(right_pane)

        layout = QGridLayout(self)
        layout.addWidget(splitter)
        self.setLayout(layout)


# noinspection PyMethodMayBeStatic
class SplitWindow(QMainWindow):

    def __init__(self, parent=None):
        super(SplitWindow, self).__init__(parent)
        self.statusBar().showMessage("Ready")
        self.resize(800, 600)
        self.setCentralWidget(self.build_layout())

    def build_layout(self):
        return QPanedWidget(
            self.create_pane(self.create_pane_content('left')),
            self.create_pane(self.create_pane_content('right')),
            Qt.Horizontal  # This is optional, defaults to horizontal
        )

    def create_pane(self, content: QLayout) -> QWidget:
        # Container widget for pane layout
        pane_layout_container = QWidget()
        pane_layout_container.setLayout(content)
        return pane_layout_container

    def create_pane_content(self, identifier) -> QLayout:
        content = QVBoxLayout()  # Layout widget for pane content

        # FROM HERE you create your own content

        toolbar = QToolBar()
        toolbar.addWidget(QPushButton("Do Something"))
        content.addWidget(toolbar)  # Don't forget this! ^_^

        label = QLabel(identifier)
        label.setAutoFillBackground(True)
        p = label.palette()
        p.setColor(label.backgroundRole(), Qt.lightGray)
        label.setPalette(p)
        label.setAlignment(Qt.AlignCenter)

        content.addWidget(label)  # Don't forget this! ^_^

        # UNTIL HERE you populate your content

        return content


if __name__ == '__main__':
    app = QApplication([])
    win = SplitWindow()
    win.show()
    app.exec_()
noughtnaut
  • 99
  • 5