afernandezody
afernandezody

Reputation: 123

How to create Signal for QDockWidget?

When QTabWidget is used, it is straightforward to call a function (e.g. on_tab_changed) when any of the tabs is clicked on with something like self.currentChanged.connect(self.on_tab_changed). However, I cannot figure out how to do similarly with QDockWidget. I was able to come up with a simplified MRE that reads:

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

class Window(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("OOP")
        self.uinterface()
        self.show()

    def uinterface(self):

        self.dock = QDockWidget("OOP example", self)
        self.listWidget = QListWidget()
        self.listWidget.addItem("One")
        self.listWidget.addItem("Two")
        self.listWidget.addItem("Three")
        self.dock.setWidget(self.listWidget)
        self.dock.currentChanged.connect(self.on_tab_changed) # This is the line that I'd like to modify

    def on_tab_changed(self, index: int) -> None:
        print ("DO SOMETHING")

App = QApplication(sys.argv)
window = Window()
sys.exit(App.exec())

This doesn't work because currentChanged is not a Signal for QDockWidget (which is for QTabWidget) although both derive from QWidget. I want to come up with a relatively simple way to accomplish this task as converting QDockWidget into QTabWidget is relatively straightforward for the MRE but a lot more complex and time consuming for the whole app.

P.S. Based on some of the comments, maybe the code could have read

    ...
    self.dock.setWidget(self.listWidget)
    self.dock.Clicked.connect(self.on_dockwidget_clicked) 

def on_dockwidget_clicked(self) -> None:
    print ("DO SOMETHING")

albeit this still would not work and it'd be necessary to use the accepted solution.

Upvotes: 0

Views: 320

Answers (1)

Alexander
Alexander

Reputation: 17291

You could overwrite the the event method a QDockWidget subclass and listen for mousePressEvents and emit a custom signal that sends some kind of identifier, in case you have multiple dockWidgets and you need to know which one sent the signal. Then you can set your mainWindow to listen for the custom signal and connect you method slot to it.

For Example:

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

class DockWidget(QDockWidget):

    hasFocus = pyqtSignal([QDockWidget])

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

    def event(self, event):
        if event.type() == QEvent.MouseButtonPress and event.button() == 1:
            self.hasFocus.emit(self)
        return super().event(event)

class Window(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("OOP")
        self.uinterface()
        self.show()

    def uinterface(self):
        self.dock = DockWidget("OOP example", self)
        self.listWidget = QListWidget()
        self.listWidget.addItem("One")
        self.listWidget.addItem("Two")
        self.listWidget.addItem("Three")
        self.dock.setWidget(self.listWidget)
        self.dock.hasFocus.connect(self.on_dock_focus)

    def on_dock_focus(self, dockwidget):
        print(f"DO SOMETHING WITH {dockwidget.objectName()}")

App = QApplication(sys.argv)
window = Window()
sys.exit(App.exec())

Upvotes: 1

Related Questions