Home > PyQt5, python > PyQt5: QDockWidget

PyQt5: QDockWidget

3 Aprile 2019

Torna all’indice degli appunti

QDockWidget

La classe QDockWidget mette a disposizione una window secondaria che può essere posizionata in un’area dedicata della QMainWindow, detta Dock Widget Area attorno al central Widget, oppure lasciata floating come Top Level Window, quindi esterna alla QMainWindow stessa.


Il DockWidget consiste di una title bar e di una content area.

Vediamo un sempio pratico così composto:
il CentralWidget della QMainWindow sarà un QTextEdit su quale verranno inseriti testi;
il DockWidget sarà un semplice QListWidget composto da qualche semplice item;

Per aggiungere il widget desiderato all’interno del QDockWidget, si usa il metodo setWidget(widget):

from PyQt5.QtWidgets import (QMainWindow, QApplication, QPushButton, QWidget,
                             QVBoxLayout, QHBoxLayout, QTextEdit, QDockWidget,
                             QListWidget)
from PyQt5.QtCore import Qt
import sys


class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        layout = QHBoxLayout()

        self.setWindowTitle("DockWidget example")
        self.dock_widget = QDockWidget("Dockable", self)
        self.list_widget = QListWidget()
        self.list_widget.addItem("item 1")
        self.list_widget.addItem("item 2")
        self.list_widget.addItem("item 3")

        self.dock_widget.setWidget(self.list_widget) # aggiungo il list-widget!
        self.dock_widget.setFloating(False)
        self.frame_widget = FrameWidget(self)
        self.setCentralWidget(self.frame_widget)
        self.addDockWidget(Qt.RightDockWidgetArea, self.dock_widget)
        self.setLayout(layout)

        self.list_widget.clicked.connect(self.on_item)

    def on_item(self):
        row = self.list_widget.currentRow()
        item = self.list_widget.item(row)
        self.frame_widget.text_string += "%s\n" % item.text()
        self.frame_widget.text_edit.setText(self.frame_widget.text_string)


class FrameWidget(QWidget):
    def __init__(self, parent):
        self.text_string = ""
        super(FrameWidget, self).__init__(parent)
        layout = QVBoxLayout(self)
        self.text_edit = QTextEdit()
        button = QPushButton("CLEAR")
        layout.addWidget(self.text_edit)
        layout.addWidget(button)
        self.setLayout(layout)
        button.clicked.connect(self.on_clear)

    def on_clear(self):
        self.text_string = ""
        self.text_edit.clear()


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

L’ancoraggio iniziale del dock-widget:

        self.addDockWidget(Qt.RightDockWidgetArea, self.dock_widget)

è modificabile alternando nel metodo addDockWidget(side, dockwidget) di QMainWindow i seguenti valori:

Qt.RightDockWidgetArea: ancoraggio destro (di default nell’esempio);
Qt.LeftDockWidgetArea: ancoraggio sinistro;

Qt.TopDockWidgetArea: ancoraggio alto;

Qt.BottomDockWidgetArea: ancoraggio basso;

Ovviamente il dock-widget è trascinabile sulle varie zone!
Trascinandolo esternamente alla main window, diventerà una secondary window.

Floatable widget

Volendo settare il dock-widget floating di default, non utilizzeremo il metodo addDockWidget di QMainWindow,
ma il metodo setFloatable(bool) del QDockWidget stesso:

...
        self.setCentralWidget(self.frame_widget)
        # self.addDockWidget(Qt.RightDockWidgetArea, self.dock_widget)
        self.dock_widget.setFloating(True)
...

DockWidget Allowed Areas

Possiamo decidere su quali aree (left, right, top, bottom) poter ancorare il dock-widget.
Basta passare al metodo di QDockWidget, setAllowedAreas(const), la costante o l’unione delle costanti rappresentanti
le aree permesse. Mettiamo di voler escludere le Dock widget area Top e Bottom, basterà scrivere:

...
        self.dock_widget.setAllowedAreas(Qt.LeftDockWidgetArea |
                                         Qt.RightDockWidgetArea)
...

Di default la costante utilizzata è: Qt.AllDockWidgetAreas

DockWidget Features

Anche le Features sono costanti che passiamo al metodo setFeatures(const) del dock-widget.
Di default sono l’unione delle seguenti:

QDockWidget.DockWidgetClosable: permette di chiudere il dock-widget;
QDockWidget.DockWidgetMovable: permette di muovere il dock-widget;
QDockWidget.DockWidgetFloatable: permette di renderlo floatable;

supponiamo di volere un dock-widget che non sia chiudibile, basterà scrivere:

...
        self.dock_widget.setFeatures(self.dock_widget.DockWidgetMovable |
                                     self.dock_widget.DockWidgetFloatable)
...

SEGNALI

I principali segnali sono:

allowedAreasChanged(allowedAreas):

il segnale viene emesso quando cambiano le regole della allowed areas:

>> from PyQt5.QtWidgets import (QMainWindow, QApplication, QPushButton, QWidget,
...                              QVBoxLayout, QHBoxLayout, QTextEdit, QDockWidget,
...                              QListWidget)
>>> from PyQt5.QtCore import Qt
>>> app = QApplication([])
>>> dw = QDockWidget("Dockable", None)
>>> def allowed_area_changed_signal():
...     print("[SIG] Allowed area changed!")
...     
>>> dw.setAllowedAreas(Qt.RightDockWidgetArea | Qt.LeftDockWidgetArea) # Aree di partenza
>>> dw.allowedAreasChanged.connect(allowed_area_changed_signal)
<PyQt5.QtCore.QMetaObject.Connection object at 0x0393DFB0>
>>> dw.setAllowedAreas(Qt.RightDockWidgetArea | Qt.LeftDockWidgetArea) # Le aree non cambiano
>>> dw.setAllowedAreas(Qt.RightDockWidgetArea) # Le Aree cambiano
[SIG] Allowed area changed!

dockLocationChanged(area):

Questo segnale viene emesso ovviamente quando la posizione del dock-widget cambia, in seguito ad uno
spostamento effettuato dall’utente.

featuresChanged(features):

Questo segnale viene emesso quando le features del dock-widget vengono modificate:

>>> def features_changed_signal():
...     print("[SIG] Dock Widget features changed!")
...     
>>> dw.featuresChanged.connect(features_changed_signal)
<PyQt5.QtCore.QMetaObject.Connection object at 0x0398F1F0>
>>> dw.setFeatures(dw.DockWidgetMovable | dw.DockWidgetFloatable)
[SIG] Dock Widget features changed!

topLevelChanged(bool):

Il segnale viene emesso quando il dock-widget diventa una top level window, ad esempio quando viene portato
all’esterno della Main Window, diventando di fatto una secondary window.
Aggiungendo il seguente codice, sarà sufficiente premere sul tastino che rende la dock-widget floatable ed il segnale
sarà emesso:

...
        self.dock_widget.topLevelChanged.connect(self.top_level_win_signal)

    def top_level_win_signal(self):
        print("[SIG] The DockWidget is now a Top Level one")
...

visibilityChanged(bool):

Il segnale viene emesso quando il widget modifica la propria visibilità:

>>> def visibility_changed_signal():
...     if dw.isVisible():
...         print("[SIG] The DockWidget is visible!")
...     else:
...         print("[SIG] The DockWidget is not visible!")
...         
>>> dw.visibilityChanged.connect(visibility_changed_signal)
<PyQt5.QtCore.QMetaObject.Connection object at 0x0393DFB0>
>>> dw.show()
[SIG] The DockWidget is visible!
>>> dw.hide()
[SIG] The DockWidget is not visible!

Torna all’indice degli appunti

Categorie:PyQt5, python Tag: ,
I commenti sono chiusi.