获取添加到QMainWindow的停靠窗口小部件的引用

4
我使用一个采用Qt编写的软件,其中有一个QMainWindow对象。当添加一个小部件到已经存在的QMainWindow对象时,我需要获取该小部件的引用。我查看了Qt文档,但是没有找到任何类似"childAdded"的事件。请检查以下代码:
import sys
from PyQt5.QtWidgets import QApplication, QPushButton, QMainWindow, QDockWidget
from PyQt5.QtCore import Qt

class MainWindow(QMainWindow):    
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)    
        self.button = QPushButton("A Button!")
        self.setCentralWidget(self.button)

def do_something(w):
    w.setWindowTitle("Newly Added")

def add_dock_widget(win):
    win.addDockWidget(Qt.RightDockWidgetArea, QDockWidget())

app = QApplication(sys.argv)
window = MainWindow()
window.show()

add_dock_widget(window)
# At this point, somehow, I need to get the reference of added widget.
# Because add_dock_widget method doesn't return any reference.

# I'm looking for something like that, so that I can manipulate the widget:
# window.childAdded[****].connect(do_something)

app.exec_()

这款软件允许在其中编写Python脚本。当向GUI添加一个子项时,我需要使用脚本对子项进行更改。


你想让Qt在QWidget添加到QMainWindow时通知你吗? - eyllanesc
当然可以。但我需要从现有的QMainWindow对象中获取。当我查看示例时,所有示例都创建了一个继承QMainWindow的新类。 - Kadir Şahbaz
嗯,你能提供一个 [mre] 以便更好地理解你吗? - eyllanesc
2个回答

5

根据您的背景目标,有几种选择:

- findChild() 或 findChildren():

如果您知道对象类,可以使用 findChild 或 findChildren:

if __name__ == '__main__':

    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()

    add_dock_widget(window)
    dockwidget = window.findChild(QDockWidget)
    do_something(dockwidget)

    # or
    # for dockwidget in window.findChildren(QDockWidget)
    # do_something(dockwidget)

    app.exec_()

但这种方法有限,因为您可能会拥有许多相同类型的小部件,并且您无法区分哪个对象是您想要的,因此您将不得不使用另一个功能传递新过滤器。

- 重写事件方法或使用事件过滤器:

class MainWindow(QMainWindow):    
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)    
        self.button = QPushButton("A Button!")
        self.setCentralWidget(self.button)

    def event(self, e):
        if e.type() == QEvent.ChildAdded:
            if isinstance(e.child(), QDockWidget):
                do_something(e.child())
        return super(MainWindow, self).event(e)

class ChildAddedFilter(QObject):
    def __init__(self, widget):
        super(ChildAddedFilter, self).__init__(widget)
        self._widget = widget
        self._widget.installEventFilter(self)

    def eventFilter(self, o, e):
        if o is self._widget and e.type() == QEvent.ChildAdded:
            if isinstance(e.child(), QDockWidget):
                do_something(e.child())
        return super(ChildAddedFilter, self).eventFilter(o, e)


if __name__ == "__main__":

    app = QApplication(sys.argv)
    window = MainWindow()
    f = ChildAddedFilter(window)
    window.show()
    add_dock_widget(window)
    app.exec_()

2
你可以直接从add_dock_widget返回dock-widget,像这样:
def add_dock_widget(win):
    dock = QDockWidget(win)
    win.addDockWidget(Qt.RightDockWidgetArea, dock)
    return dock

app = QApplication(sys.argv)
window = MainWindow()
window.show()

dock = add_dock_widget(window)

do_something(dock)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接