Planned maintenance has been done but it did not solve the problem. So work will continue on this and a new time for trying updates will be announced asap.

[pyqt5] How to Trigger an update of the QTreeView after adjusting the Geometry after undocking



  • Using : python 3.7 pyqt5 windows10

    When undocking I resize the main window to be the size it would have been without the DockWindow but in doing so the right two columns disappear out of view. I have tried various events to try and trigger an adjustment to that TreeView but to no avail. The code I have included has the issue just click one of the Docks and then detach the resulting window from the Main Window and you can see what I mean. As always any help is greatly appreciated.

    I have tried the following:

    self.updateGeometry()
    self.CenterPane.updateGeometry()
    self.CenterPane.ItemDsply.updateGeometry()
    
    self.resizeEvent(QResizeEvent(self.size(), QSize()))
    self.CenterPane.resizeEvent(QResizeEvent(self.size(), QSize()))
    self.CenterPane.ItemDsply.resizeEvent(QResizeEvent(self.size(), QSize()))
    

    Here is a working example:

    from sys  import exit as sysExit
    from math import trunc
    
    from PyQt5.QtCore    import *
    from PyQt5.QtGui     import *
    from PyQt5.QtWidgets import *
    
    class CustomItemModel(QStandardItemModel):
        def headerData(self, section, orientation, role):
            if role == Qt.ForegroundRole:
                brush = QBrush()
                brush.setColor(Qt.blue)
                brush.setStyle(Qt.SolidPattern)
                return brush
                  
            elif role == Qt.BackgroundRole:
                brush = QBrush()
                brush.setColor(Qt.yellow)
                brush.setStyle(Qt.SolidPattern)
                return brush
              
            elif role == Qt.FontRole:
                font = QFont()
                font.setBold(True)
                font.setPointSize(10)
                return font
                  
            return super().headerData(section, orientation, role)
    
    class DockWin1(QDockWidget):
        def __init__(self, parent):
            QDockWidget.__init__(self)
            
            self.setWindowTitle('Dock 1')
            self.MainWin = parent
    
            self.container = QWidget(self)
            self.container.setLayout(QHBoxLayout())
            self.setWidget(self.container)
            self.container.layout().addWidget(QTextEdit())
            self.setMinimumWidth(100)
            self.setMinimumHeight(100)
    
            self.topLevelChanged.connect(self.SetDock1Free)
    
        @property
        def MainWin(self):
            return self.__parent
    
        @MainWin.setter
        def MainWin(self, value):
            self.__parent = value
    
        def closeEvent(self, event):
            self.MainWin.ClosingDock1()
    
        def SetDock1Free(self):
            if self.MainWin.Dock1Free:
                self.MainWin.CheckToResize('Dock1', 100)
            else:
                self.MainWin.CheckToResize('Dock1', self.width())
    
            self.MainWin.Dock1Free = not self.MainWin.Dock1Free
    
    class DockWin2(QDockWidget):
        def __init__(self, parent):
            QDockWidget.__init__(self)
            
            self.setWindowTitle('Dock 2')
            self.MainWin = parent
    
            self.container = QWidget(self)
            self.container.setLayout(QHBoxLayout())
            self.setWidget(self.container)
            self.container.layout().addWidget(QTextEdit())
            self.setMinimumWidth(100)
            self.setMinimumHeight(100)
    
            self.topLevelChanged.connect(self.SetDock2Free)
    
        @property
        def MainWin(self):
            return self.__parent
    
        @MainWin.setter
        def MainWin(self, value):
            self.__parent = value
    
        def closeEvent(self, event):
            self.MainWin.ClosingDock2()
    
        def SetDock2Free(self):
            if self.MainWin.Dock2Free:
                self.MainWin.CheckToResize('Dock2', 100)
            else:
                self.MainWin.CheckToResize('Dock2', self.width())
    
            self.MainWin.Dock2Free = not self.MainWin.Dock2Free
    
    class ItemDsplyr(QTreeView):
        def __init__(self, CentrPane):
            QTreeView.__init__(self, CentrPane)
            self.CntrPane = CentrPane
    
            self.setEditTriggers(QTreeView().NoEditTriggers)
            self.model = CustomItemModel(0, 3)
            self.model.setHorizontalHeaderLabels(['1st Col', '2nd Col', '3rd Col'])
            self.model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole)
            self.setModel(self.model)
            self.setMinimumWidth(250)
    
            self.header().setStretchLastSection(False)
            self.header().setSectionResizeMode(0, QHeaderView.Stretch)
            self.setColumnWidth(1, 75)
            self.setColumnWidth(2, 100)
    
    class CenterPanel(QWidget):
        def __init__(self, MainWin):
            QWidget.__init__(self)
    
            self.MyEditor = QTextEdit('Editorial')
            self.ItemDsply = ItemDsplyr(self)
    
            CntrPane = QSplitter(Qt.Horizontal, self)
            CntrPane.addWidget(self.MyEditor)
            CntrPane.addWidget(self.ItemDsply)
            CntrPane.setSizes([50,200])
            CntrPane.setCollapsible(0, False)
            CntrPane.setCollapsible(1, False)
    
            hbox = QHBoxLayout(self)
            hbox.addWidget(CntrPane)
    
            self.setLayout(hbox)
    
    class MenuToolBar(QDockWidget):
        def __init__(self, MainWin):
            QDockWidget.__init__(self)
            self.MainWin = MainWin
            self.MainMenu = MainWin.menuBar()
    
            self.WndowMenu  = self.MainMenu.addMenu('Windows')
    
            self.Dock1Act = QAction('Dock1', self)
            self.Dock1Act.setStatusTip('Open the Dock1 Window')
            self.Dock1Act.triggered.connect(MainWin.ShowDock1)
    
            self.Dock2Act = QAction('Dock2', self)
            self.Dock2Act.setStatusTip('Open the Dock2 Window')
            self.Dock2Act.triggered.connect(MainWin.ShowDock2)
    
            self.WndowMenu.addAction(self.Dock1Act)
            self.WndowMenu.addSeparator()
            self.WndowMenu.addAction(self.Dock2Act)
    
            self.InitToolBar(MainWin)
    
        def InitToolBar(self, MainWin):
            self.mainToolBar = MainWin.addToolBar("Quick Access")
    
            self.mainToolBar.addAction(self.Dock1Act)
            self.mainToolBar.addSeparator()
            self.mainToolBar.addAction(self.Dock2Act)
    
    class UI_MainWindow(QMainWindow):
        def __init__(self, MainDesktop):
            super(UI_MainWindow, self).__init__(MainDesktop)
            self.setWindowTitle('Main Window')
            self.Dock1Open = False
            self.Dock1Free = False
            self.Dock2Open = False
            self.Dock2Free = False
    
            self.MnDskTop = MainDesktop
    
          # Left, Top, Width, Height
            self.setGeometry(200, 200, 550, 550)
     
            self.CenterPane = CenterPanel(self)
            self.setCentralWidget(self.CenterPane)
    
            self.MenuToolBar = MenuToolBar(self)
    
        def ShowDock1(self):
            if not self.Dock1Open:
                self.CheckToResize('Dock1', 300)
                self.Dock1 = DockWin1(self)
                self.Dock1Open = True
                self.Dock1Free = False
                self.addDockWidget(Qt.RightDockWidgetArea, self.Dock1)
    
        def ClosingDock1(self):
            self.Dock1Open = False
    
        def ShowDock2(self):
            if not self.Dock2Open:
                self.CheckToResize('Dock2', 300)
                self.Dock2 = DockWin2(self)
                self.Dock2Open = True
                self.Dock2Free = False
                self.addDockWidget(Qt.RightDockWidgetArea, self.Dock2)
    
        def ClosingDock2(self):
            self.Dock2Open = False
    
        def CheckToResize(self, WinDocked, DockWdth):
          # If any of the other docks are open and docked do not resize
            if   self.Dock1Open and WinDocked != 'Dock1' and not self.Dock1Free:
                return
            elif self.Dock2Open and WinDocked != 'Dock2' and not self.Dock2Free:
                return
    
            Docking = True
            if   WinDocked == 'Dock1' and self.Dock1Open != self.Dock1Free:
                Docking = False
            elif WinDocked == 'Dock2'  and self.Dock2Open != self.Dock2Free:
                Docking = False
    
            WinLeft  = self.geometry().left()
            WinTop   = self.geometry().top()
            WinWidth = self.geometry().width()
            WinHight = self.geometry().height()
            ScrWidth = self.MnDskTop.screenGeometry().width()
    
          # Docking
            if Docking:
                if ScrWidth < (WinLeft + WinWidth + DockWdth):
                    WinLeft  = 0
                    WinWidth = ScrWidth
                elif WinLeft > (trunc(DockWdth/2)):
                    WinLeft = WinLeft - trunc(DockWdth/2)
                    WinWidth = WinWidth + DockWdth
                else:
                    WinLeft = 0
                    WinWidth = WinWidth + DockWdth
    
                self.setGeometry(WinLeft, WinTop, WinWidth, WinHight)
         # Un-Docking
            else:
                WinWidth = WinWidth - DockWdth
                self.setGeometry(WinLeft, WinTop, WinWidth, WinHight)
              # Call the Event that Triggers View Adjustment ?? 
                self.CenterPane.ItemDsply.updateGeometry()
    #            self.CenterPane.ItemDsply.resizeEvent(QResizeEvent(self.size(), QSize()))
    
    if __name__ == '__main__':
        MainApp = QApplication([])
    
        MainGui = UI_MainWindow(MainApp.desktop())
        MainGui.show()
    
        sysExit(MainApp.exec_())
    
    

    As stated I am trying to get the QTreeView to adjust appropriately to the newly sized window so that it shows all three columns. Currently it shoves the last to columns out of view.



  • Following answer given elsewhere -- add the setSizeAdjustPolicy to the ItemDisplyr as follows:

            self.setMinimumWidth(250)
    
            self.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContents)
    
            self.header().setStretchLastSection(False)
    

    And I needed to change reset the Geometry of my ItemDsply when undocking to just resize as follows

                WinWidth = WinWidth - DockWdth
                self.resize(WinWidth, WinHight)
    

Log in to reply