QDockWidget is a very nice widget that allows you to leave layout adjustments to the user. However, it is also true that there are many places where I wonder, "Can I do this?" (Qt seems to be out of reach of itchy places in the standard state as a whole)
Let's raise the inconvenience with QDockWidget.
--Icon does not appear in the title bar --Icon is not displayed on the tab when tabbed --Toolbar cannot be placed in DockWidget --Cannot be tabbed in Float state (this has been solved with Qt5.5)
Tabbing in the last Float state is supported by Qt5.5, so it is not supported here. Wait for the completion of PySide 2 for Qt5.
Let's solve it in order from the top.
** Suddenly abandoned. ** **
As the number of DockWidgets increases, the visibility of which Dock has which function decreases. It would be convenient if the icon set by QDockWidget :: setWindowIcon is displayed in the title bar.
But that seems difficult.
Draw your own Drop Indicator with PySide (realize QProxyStyle with black magic)
Hook the drawControl in the title bar with the ProxyStyle used in the article above.
def drawControl(self, element, option, painter, widget):
if element == QStyle.CE_DockWidgetTitle:
width = self.pixelMetric(QStyle.PM_ToolBarIconSize)
margin = self.pixelMetric(QStyle.PM_DockWidgetTitleMargin)
painter.drawPixmap(margin, margin, widget.windowIcon().pixmap(QSize(width / 2, width / 2)))
option.rect.adjust(width, 0, 0, 0)
return self._style.drawControl(element, option, painter, widget)
The icon is drawn by itself, the display range is shifted by the icon, and it is passed to the original drawing. However, the result is as follows: The background of the icon part is not filled.
In order to avoid this situation, I read the Qt source, but it is hard-coded. If you do, you have to draw all the title bars yourself. In any case, the title bar in the Float state is a separate implementation after a hard implementation, so that also needs to be reimplemented.
I gave up because there were too few rewards for my hard work.
To display the icon on the title bar, display the icon inside the dock. However, it is not good that the icon is not displayed on the tabbed tab. Since the contents of the dog cannot be seen, it can be recognized only by the characters on the tab, and there is a big problem in visibility.
When QDockWidget is tabbed, the tab is stored in QTabBar in QMainWindow. But that tab and the QDock Widget are completely separate things.
So let's solve it in a slightly rough way, take a look at the code below.
#! usr/bin/python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals, print_function, absolute_import
import sys
from PySide.QtCore import *
from PySide.QtGui import *
def main():
app = QApplication(sys.argv)
main_window = QMainWindow()
warning_icon = QApplication.style().standardIcon(QStyle.SP_MessageBoxWarning)
critical_icon = QApplication.style().standardIcon(QStyle.SP_MessageBoxCritical)
dock_1 = QDockWidget("warning", main_window)
dock_1.setWindowIcon(warning_icon)
dock_2 = QDockWidget("critical", main_window)
dock_2.setWindowIcon(critical_icon)
main_window.addDockWidget(Qt.LeftDockWidgetArea, dock_1)
main_window.addDockWidget(Qt.RightDockWidgetArea, dock_2)
def onLocationChanged(area):
icon_dict = {}
for _dock in main_window.findChildren(QDockWidget):
icon_dict[_dock.windowTitle()] = _dock.windowIcon()
for tab_bar in main_window.findChildren(QTabBar):
for idx in range(tab_bar.count()):
if tab_bar.tabText(idx) in icon_dict:
tab_bar.setTabIcon(idx, icon_dict[tab_bar.tabText(idx)])
for dock in main_window.findChildren(QDockWidget):
dock.dockLocationChanged.connect(onLocationChanged)
onLocationChanged(0)
main_window.show()
app.exec_()
if __name__ == "__main__":
main()
The execution result is as follows, the icon is displayed on the tabbed DockWidget.
What I'm doing is checking the tabs of QTabBar under the main window every time the layout of QDockWidget is changed, and setting the icon to the tab with the same title name.
It's a brute force method, but as far as I read the Qt source, there seems to be no other solution. The layout pointer is stored in QTabBar :: tabData, but the user program cannot determine the QDockWidget from the pointer. On the user program side, there is only an element that connects only the tab name and the title name of QDockWidget.
You cannot place the toolbar of the main window inside the QDockWidget, but you can have a separate toolbar for each QDockWidget.
#! usr/bin/python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals, print_function, absolute_import
import sys
from PySide.QtCore import *
from PySide.QtGui import *
def main():
app = QApplication(sys.argv)
main_window = QMainWindow()
home_icon = QApplication.style().standardIcon(QStyle.SP_DirHomeIcon)
drive_icon = QApplication.style().standardIcon(QStyle.SP_DriveDVDIcon)
home_action = QAction(home_icon, "Home", main_window)
drive_action = QAction(drive_icon, "Drive", main_window)
dock_1 = QDockWidget("warning", main_window)
dock_2 = QDockWidget("critical", main_window)
main_window.addDockWidget(Qt.LeftDockWidgetArea, dock_1)
main_window.addDockWidget(Qt.RightDockWidgetArea, dock_2)
def create_dock_toolbar(dock):
__main_window = QMainWindow()
__main_window.setParent(dock)
dock.setWidget(__main_window)
return __main_window
_main_window = create_dock_toolbar(dock_1)
bar = QToolBar(_main_window)
bar.addActions([home_action, drive_action])
_main_window.addToolBar(bar)
_main_window = create_dock_toolbar(dock_2)
bar = QToolBar(_main_window)
bar.addActions([home_action, drive_action])
_main_window.addToolBar(bar)
main_window.show()
app.exec_()
if __name__ == "__main__":
main()
You can see that each of the two QDock Widgets has a toolbar.
Only QMainWindow can be placed on the toolbar. So, each QDockWidget has a QMainWindow as a child, and the toolbar is placed there.
Qt is a great GUI tool, but the state of the element is inconvenient.
Since the drawing is done completely by Qt, anything can be freely implemented. However, there are too many situations that the user has to implement in full with a little expansion. (This is a lot of hard coding with no extensibility rather than Qt's design being too lax)
If you think that there is a smarter solution just because you lack knowledge, please teach us.
Recommended Posts