[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)