我有一个应用程序,它有一个主窗口,可以有多个子窗口。我想在主窗口中有一组与当前所选窗口交互的QActions。例如,应用程序可能是文本编辑器,单击file-> save应保存用户当前正在处理的文本文件。此外,某些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(self)这样的小函数,只是为了将每个动作重定向到正确的位置。
答案 0 :(得分:1)
是的,这可以通过处理QMenu的aboutToShow信号来实现 并考虑QGuiApplication的焦点窗口(或者你在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)