我在Controller.py文件中有一个QMainWindow
,它在centralWidget上创建了一个QmenuBar
,并且多个文件分别命名为win0.py,win1.py,...,嵌套在{{ 1}}。
现在,我想启用/禁用Controller的mainWindow菜单栏中的按钮,并在centralWidget中获得一些变量/调用功能
此示例基于以下无法回答我的问题:
Using QStackedWidget for multi-windowed PyQt application
How to make nested StackedLayouts in PyQt5?
最接近的问题是:
Setting up stateChanged signal in QStackedWidget, pyqt
但是它们都没有更改MainWindow(控制器)上的项目,就像我尝试做的那样。有关详细信息,请参见代码。
controller.py:
QstackedLayout
win0.py(win1.py ...相同的基本原理)
import sys
from PyQt5.QtWidgets import *
from PyQt5 import QtCore
from win0 import W0 # sample window
#from win1 import W1 # further windows
#from win2 import W2
class Controller (QMainWindow):
def __init__(self, parent=None):
#super(Controller, self).__init__(parent)
QMainWindow.__init__(self, parent)
# used variables
self.winDict = {}
self.v1 = " self.V1 in Controller"
# create stack
self.stackLayout = QStackedLayout ()
# put stack on MainWindow
self.MainWidget =QWidget()
self.MainWidget.setLayout(self.stackLayout)
self.setCentralWidget(self.MainWidget)
self.init_MenuBar ()
# add further layouts
self.init_Windows()
# swith to first layout
self.activeWin = self.switchWin (0)
def init_MenuBar(self):
self.toolbarButton_file = QPushButton (self.tr ("File"))
self.toolbarButton_0 = QPushButton (self.tr ("Win0"))
self.toolbarButton_1 = QPushButton (self.tr ("Win1"))
self.toolbarButton_2 = QPushButton (self.tr ("Win2"))
toolbar = self.addToolBar ("Window Manager")
toolbar.addWidget (self.toolbarButton_file)
toolbar.addWidget (self.toolbarButton_0)
toolbar.addWidget (self.toolbarButton_1)
toolbar.addWidget (self.toolbarButton_2)
toolbar.setMovable (False)
self.toolbarButton_0.clicked.connect ( (lambda: self.switchWin (0)))
self.toolbarButton_1.clicked.connect ((lambda: self.switchWin (1)))
self.toolbarButton_2.clicked.connect ((lambda: self.switchWin (2)))
self.toolbarButton_0.setCheckable (False)
self.toolbarButton_1.setCheckable(False)
self.toolbarButton_2.setCheckable(False)
self.toolbarButton_0.setEnabled (True)
self.toolbarButton_1.setEnabled (True)
self.toolbarButton_2.setEnabled (True)
def init_Windows(self):
self.switchWin(0, True)
self.switchWin(1, True)
self.switchWin(2, True)
def switchWin(self, id=0, initonly = False):
print ("-> switchWin:", id)
if id not in self.winDict.keys ():
if id == 0:
self.winDict[id] = W0 ()
#elif id == 1:
# self.winDict[id] = W1 ()
#elif id == 2:
# self.winDict[id] = W2 ()
self.stackLayout.addWidget (self.winDict[id])
if not initonly:
self.stackLayout.setCurrentIndex (id)
Window = self.winDict[id]
return Window
def list_v1(self):
print("-> Controller.list_V1")
print("V1:", self.v1)
def main():
App = QApplication(sys.argv)
ProgramWindow = Controller()
ProgramWindow.show()
App.exec_()
if __name__ == "__main__":
main()
win0.ui(与win1.ui相同)
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
class W0(QMainWindow):
def __init__(self):
super().__init__()
self.ui = self.init_UI()
self.v1 ="Variable in W0"
self.ui.pushButton.clicked.connect (self.pbClicked)
def init_UI(self):
mainForm = ("win0.ui")
print ("mainForm:", mainForm)
Widget = uic.loadUi (mainForm, self)
return Widget
def pbClicked(self):
print ("-> win0.pbClicked")
self.parent().toolbarButton_0.setEnabled (False) # There is the question
# How to access widgets and functions, variables on the
# centralWidget or MainWindow of Controller.py. I want to en/disable button in the menuBar e.g.
if __name__ == "__main__":
App = QApplication (sys.argv)
ProgramWindow = W0()
ProgramWindow.show ()
App.exec_ ()
使用pyqt5和python 3.7。我尝试使用
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>10</x>
<y>0</y>
<width>43</width>
<height>13</height>
</rect>
</property>
<property name="text">
<string>Win 0</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>60</x>
<y>0</y>
<width>80</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton_0">
<property name="geometry">
<rect>
<x>180</x>
<y>0</y>
<width>80</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>PushButton_0</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>20</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
导致无限循环,而import from Controller
导致
self.parent().toolbarButton_0.setEnabled (False)
答案 0 :(得分:0)
您可以使用信号和插槽进行通信,而不是尝试直接从Controller
操作W0
小部件。例如,在W0
中,您可以执行类似的操作
class W0(QMainWindow):
button_clicked = QtCore.pyqtSignal()
def __init__(self):
...
self.ui.pushButton.clicked.connect(self.pbClicked)
....
def pbClicked(self):
print (f"-> win{self.id}.pbClicked")
self.button_clicked.emit()
在Controller
class Controller(QMainWindow):
....
def switchWin(self, id=0, initonly = False):
print ("-> switchWin:", id)
if id not in self.winDict.keys ():
if id == 0:
self.winDict[id] = W0 ()
self.winDict[id].button_clicked.connect(self.W0_button_clicked)
....
def W0_button_clicked(self):
self.toolbarButton_0.setEnabled (False)
当然,在Controller.SwitchWin
中,您可以直接连接到信号self.winDict[id].ui.pushButton.clicked
,但是在W0
中创建一个单独的信号,并在单击按钮时发出该信号,它具有以下优点:更改W0
的Gui,而不必重写Controller
中的信号槽连接。另外,如果需要,可以通过指定信号的输入参数来使用信号发送其他数据。