如何从stackedLayout访问centralWidget中的小部件?
Posted
技术标签:
【中文标题】如何从stackedLayout访问centralWidget中的小部件?【英文标题】:How to access widgets in centralWidget from stackedLayout? 【发布时间】:2019-08-24 11:16:38 【问题描述】:我在 Controller.py 文件中有一个 QMainWindow
,它在 centralWidget 上创建了一个 QmenuBar
,并在 QstackedLayout
中嵌套了多个名为 win0.py、win1.py、... 的文件。
现在我想在Controller的主窗口中启用/禁用菜单栏中的按钮,并在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:
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.py(win1.py ...同基础)
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_ ()
win0.ui(win1.ui中相同...)
<?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>
使用 pyqt5 和 python 3.7。我试着用
import from Controller
导致无限循环和self.parent().toolbarButton_0.setEnabled (False)
导致AttributeError: 'QWidget' object has no attribute 'toolbarButton_0'
【问题讨论】:
使用槽和信号,而不是尝试直接从W0
操作Controller
。
好的,请给我一个例子。我已经尝试过了,但似乎我做错了。
我发布了一个小例子。
【参考方案1】:
您可以使用信号和槽进行通信,而不是尝试直接从W0
操作Controller
小部件。例如,在W0
中,您可以执行类似的操作
class W0(QMainWindow):
button_clicked = QtCore.pyqtSignal()
def __init__(self):
...
self.ui.pushButton.clicked.connect(self.pbClicked)
....
def pbClicked(self):
print (f"-> winself.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
中创建一个单独的信号并在单击按钮时发出它的优点是你可以更改@987654330 的 Gui @ 无需重写Controller
中的信号槽连接。此外,如果需要,您可以通过为信号指定输入参数来使用该信号发送额外的数据。
【讨论】:
以上是关于如何从stackedLayout访问centralWidget中的小部件?的主要内容,如果未能解决你的问题,请参考以下文章
如何将 maven 工件从 jcenter 同步到 maven Central?
如何使用 Gradle 中的本地 JUnit Jar 而不是 Maven Central?
使 Sonatype Nexus 存储库可公开访问,以便能够下载带有 maven Central 等 URL 的工件