在PyQt中,如何使得共享菜单和工具栏与当前活动的子窗口进行通讯?

2024-10-01 05:06:46 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个应用程序,它有一个主窗口,可以有多个子窗口。我希望在主窗口中有一组与当前选定窗口交互的QActions。例如,该应用程序可能是一个文本编辑器,单击“文件”->“保存”将保存用户当前正在处理的文本文件。另外,有些qaction是可检查的,因此它们的检查状态应该反映当前活动窗口的状态。在

下面是一个最低限度的工作示例,它具有我想要的基本功能,但我怀疑有更好的方法来实现它(代码下面将进一步讨论)。在

import sys
import PyQt4.QtGui as QtGui

class DisplayWindow(QtGui.QWidget):
    def __init__(self, parent=None, name="Main Window"):
        # run the initializer of the class inherited from
        super(DisplayWindow, self).__init__()

        self.myLayout = QtGui.QFormLayout()

        self.FooLabel = QtGui.QLabel(self)
        self.FooLabel.setText(name)

        self.myLayout.addWidget(self.FooLabel)
        self.setLayout(self.myLayout)

        self.is_foo = False

    def toggle_foo(self):
        self.is_foo = not self.is_foo
        if self.is_foo:
            self.FooLabel.setText('foo')
        else: 
            self.FooLabel.setText('bar')

class WindowActionMain(QtGui.QMainWindow):
    def __init__(self):
        super(WindowActionMain, self).__init__()

        self.fooAction = QtGui.QAction('Foo', self) 
        self.fooAction.triggered.connect(self.set_foo)
        self.fooAction.setCheckable(True)

        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(self.fooAction)
        self.toolbar = self.addToolBar('File')
        self.toolbar.addAction(self.fooAction)

        self.centralZone = QtGui.QMdiArea()
        self.centralZone.subWindowActivated.connect(
                               self.update_current_window)
        self.setCentralWidget(self.centralZone)
        self.create_dw("Window 1")
        self.create_dw("Window 2")

    def create_dw(self, name):
        dw = DisplayWindow(name=name)
        self.centralZone.addSubWindow(dw)
        dw.show()

    def update_current_window(self):
        """ redirect future actions to affect the newly selected window,
        and update checked statuses to reflect state of selected window"""

        current_window = self.centralZone.activeSubWindow()
        if current_window:
            self.current_dw = self.centralZone.activeSubWindow().widget()

        self.fooAction.setChecked(self.current_dw.is_foo)

    def set_foo(self):
        self.current_dw.toggle_foo()

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    ex = WindowActionMain()
    ex.show()
    sys.exit(app.exec_())

我的DisplayWindow的实际版本可能在许多不同的项目中都很有用,我希望将其打包,这样您就不必在主窗口中添加大量代码来使用它。因此,DisplayWindow、它的所有功能和可用操作的列表应该位于一个模块中,该模块将导入到WindowActionMain的模块中。然后我应该能够为DisplayWindow添加更多的操作,而不需要更改WindowActionMain中的任何代码。特别是,我不想写一个像WindowActionMain.set_foo窗口操作main.set_foo(自我)只是把每一个动作重新定位到正确的地方。在


Tags: nameselffooinitisdefcurrentwindow
1条回答
网友
1楼 · 发布于 2024-10-01 05:06:46

是的,这可以通过处理QMenu的about to show信号来实现
考虑到qgui应用程序的focusWindow(或者在Qt4中得到的结果)。
下面的示例显示了作用于最前面窗口的通用“窗口”菜单。在

http://doc.qt.io/qt-4.8/qmenu.html#aboutToShow
http://doc.qt.io/qt-5/qguiapplication.html#focusWindow

def on_windowMenu_aboutToShow(self):
    self.windowMenu.clear()
    self.newWindowAction = QtWidgets.QAction(self)
    self.newWindowAction.setShortcut("Ctrl+n")
    self.newWindowAction.triggered.connect(self.on_newWindowAction)
    self.newWindowAction.setText("New Window")
    self.windowMenu.addAction(self.newWindowAction)
    self.windowMenu.addSeparator()
    playerWindows = [w for w in self.topLevelWindows() if w.type()==QtCore.Qt.Window and w.isVisible()]
    for i, w in enumerate(playerWindows):
        def action(i,w):
            a = QtWidgets.QAction(self)
            a.setText("Show Window {num} - {title}".format(num=i+1, title=w.title()))
            a.triggered.connect(lambda : w.requestActivate())
            a.triggered.connect(lambda : w.raise_())
            self.windowMenu.addAction(a)
        action(i,w)
    self.windowMenu.addSeparator()
    self.closeWindowAction = QtWidgets.QAction(self)
    self.closeWindowAction.setShortcut("Ctrl+w")
    self.closeWindowAction.triggered.connect(lambda : self.focusWindow().close())
    self.closeWindowAction.setText("Close")
    self.windowMenu.addAction(self.closeWindowAction)

相关问题 更多 >