PyQT4 - 更换主窗口中的控件

2 投票
2 回答
1597 浏览
提问于 2025-04-17 07:00

我刚开始学习PyQT4,遇到了下面的问题。

有一个应用程序需要在一个界面上收集用户的数据,然后在点击按钮后显示下一个界面。

main.py

app = QtGui.QApplication(sys.argv)
#here I create main window with inherited class
w = SAN_MainWindow()
#and apply some basic geometry
w.SetUI()
#here first screen rendered and button event applyed
w.ApplyWidget( SAN_Intro() )
w.show()
sys.exit(app.exec_())

第一个界面的显示是正确的。

SAN_MainWindow.py:

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

    def SetUI(self):
        self.setObjectName(_fromUtf8("MainWindow"))
        self.resize(789, 602)
        self.setWindowTitle(QtGui.QApplication.translate("MainWindow", "MainWindow", None, QtGui.QApplication.UnicodeUTF8)) 
        self.central_widget = QtGui.QWidget(self)   
        self.central_widget.setObjectName(_fromUtf8("central_widget"))
        self.setCentralWidget(self.central_widget)

    def ApplyWidget( self, widget ):
        self.active_widget = widget
        self.active_widget.Setup(self.central_widget)
        self.active_widget.SetControls( self )

    def RemoveActiveWidget( self ):
        self.active_widget.widget().setParent(None)

    def ShowInstruction( self ):
        self.RemoveActiveWidget()
        self.ApplyWidget( SAN_Instruction() )
        #self.centralWidget().update() <- Problem

SAN_Intro.py:

class SAN_Intro(object):
    def __init__(self):
        super(SAN_Intro, self).__init__()

    def Setup(self, widget):
        self.gridLayoutWidget = QtGui.QWidget(widget)
        self.gridLayoutWidget.setGeometry(QtCore.QRect(80, 30, 638, 451))
        self.gridLayoutWidget.setObjectName(_fromUtf8("gridLayoutWidget"))
        self.gridLayout = QtGui.QGridLayout(self.gridLayoutWidget)
        self.gridLayout.setContentsMargins(-1, 16, 16, -1)
        self.gridLayout.setObjectName(_fromUtf8("gridLayout"))
        #a lot of form inputs instructions....
    def SetControls( self, main_window ):
        QtCore.QObject.connect(self.pushButton, QtCore.SIGNAL("clicked()"), main_window.ShowInstruction)

    def widget(self):
        return self.gridLayoutWidget

SAN_Instruction 和 SAN_Intro 几乎是一样的,只是在设置时有不同的命令:

class SAN_Instruction(object):

    def __init__(self):
        super(SAN_Instruction, self).__init__()

    def Setup(self, widget):
        self.verticalLayoutWidget = QtGui.QWidget(widget)
        self.verticalLayoutWidget.setGeometry(QtCore.QRect(40, 20, 591, 521))
        self.verticalLayoutWidget.setObjectName(_fromUtf8("verticalLayoutWidget"))
        self.verticalLayout = QtGui.QVBoxLayout(self.verticalLayoutWidget)
        self.verticalLayout.setMargin(0)
        self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
        #a lot of form inputs instructions.... 

    def SetControls( self, main_window ):
        pass

    def widget(self):
        return self.verticalLayoutWidget

这里是我的问题: 我该如何显示第二个(通过 SAN_Instruction 动态生成的)界面呢? 我尝试更新/显示/重绘主窗口/中央窗口/父窗口。 但是在点击按钮后,我得到的只是 self.RemoveActiveWidget()。

也许我的想法不太对?

提前谢谢大家!

2 个回答

0

你可以使用“QtGui.QStackedWidget()”。你可以把窗口分成多个框架,然后把每个框架添加到QStackedWidget()里。接着,你可以用setCurrentWidget()这个函数来选择显示哪个框架,也就是在不同的框架之间切换。

self.central_widget.addWidget(self.mainFrame)
self.central_widget.setCurrentWidget(self.mainFrame)
2

你的代码还不完整,不过我建议你可以使用hide()这个方法。你可以在按钮的功能里定义这个方法,这样你不想显示的所有小部件就可以被隐藏起来,而在同一个功能里再调用你想要显示的小部件。这样做我觉得挺好的,因为可以让我的项目更有条理,也更容易追踪和调试。此外,如果需要的话,你还可以用show()这个方法把那些小部件再显示出来。

撰写回答