如何从stackedLayout访问centralWidget中的小部件?

时间:2019-08-24 11:16:38

标签: python pyqt pyqt5

我在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)

1 个答案:

答案 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中的信号槽连接。另外,如果需要,可以通过指定信号的输入参数来使用信号发送其他数据。