【问题标题】:Multi-dialog program in PyQT will not close (the sequel!)PyQT 中的多对话框程序不会关闭(续集!)
【发布时间】:2011-03-05 15:57:10
【问题描述】:

我有另一个关于 PyQT 的问题,这次我有一个更有用的示例,因为它包含我的部分代码(当然是去齿的!)我很难弄清楚如何关闭“程序选择”仅使用“注销”按钮的对话窗口。我可以简单地使用表单上的关闭按钮,但我想使用“注销”按钮来完成。

谁能帮我解决这个难题?

这里有一些可编译的代码供大家参考。

connectionName = 'example'

class SelectProgramForm(QtGui.QDialog):   
    def __init__(self, connName, connPrivilege):
        QtGui.QWidget.__init__(self)
        self.fooA = connName
        self.fooB = connPrivilege

        self.widgetWidth = 100
        self.formWidth = self.widgetWidth + 40

    def setupUi(self, programSelectForm):
        programSelectForm.setObjectName("programSelectForm")
        programSelectForm.resize(400, self.formWidth)
        self.widget = QtGui.QWidget(programSelectForm)
        self.widget.setGeometry(QtCore.QRect(20, 20, 360, self.widgetWidth))
        self.widget.setObjectName("widget")
        self.verticalLayout = QtGui.QVBoxLayout(self.widget)
        self.verticalLayout.setObjectName("verticalLayout")
        self.instructionLabel = QtGui.QLabel(self.widget)
        self.instructionLabel.setObjectName("instructionLabel")
        self.verticalLayout.addWidget(self.instructionLabel)
        spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
        self.verticalLayout.addItem(spacerItem)
        self.optionsGridLayout = QtGui.QGridLayout()
        self.optionsGridLayout.setObjectName("optionsGridLayout")


        self.verticalLayout.addLayout(self.optionsGridLayout)
        spacerItemUpper = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
        self.verticalLayout.addItem(spacerItemUpper)
        self.horizontalLayout = QtGui.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        spacerItemLower = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItemLower)
        self.pushButtonLogout = QtGui.QPushButton(self.widget)
        self.pushButtonLogout.setObjectName("pushButtonLogout")
        self.horizontalLayout.addWidget(self.pushButtonLogout)
        self.verticalLayout.addLayout(self.horizontalLayout)

        self.connect(self.pushButtonLogout, QtCore.SIGNAL("clicked()"), self.reject)

        self.retranslateUi(programSelectForm)
        QtCore.QMetaObject.connectSlotsByName(programSelectForm)


    def retranslateUi(self, programSelectForm):
        programSelectForm.setWindowTitle(QtGui.QApplication.translate("programSelectForm", "Program Select", None, QtGui.QApplication.UnicodeUTF8))
        self.instructionLabel.setText(QtGui.QApplication.translate("programSelectForm", "Select the program that you wish to access:", None, QtGui.QApplication.UnicodeUTF8))
        self.pushButtonLogout.setText(QtGui.QApplication.translate("programSelectForm", "Logout", None, QtGui.QApplication.UnicodeUTF8))


class LoginForm(QtGui.QDialog): 
    def __init__(self, connName):
        self.fooA = connName

    def setupUi(self, LoginForm):
        LoginForm.setObjectName("LoginForm")
        LoginForm.resize(275, 175)
        self.widget = QtGui.QWidget(LoginForm)
        self.widget.setGeometry(QtCore.QRect(10, 10, 251, 147))
        self.widget.setObjectName("widget")
        self.verticalLayout = QtGui.QVBoxLayout(self.widget)
        self.verticalLayout.setObjectName("verticalLayout")
        self.dataInputLayout = QtGui.QHBoxLayout()
        self.dataInputLayout.setObjectName("dataInputLayout")
        self.labelVerticalLayout = QtGui.QVBoxLayout()
        self.labelVerticalLayout.setObjectName("labelVerticalLayout")
        self.userIDLabel = QtGui.QLabel(self.widget)
        self.userIDLabel.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
        self.userIDLabel.setObjectName("userIDLabel")
        self.labelVerticalLayout.addWidget(self.userIDLabel)
        self.passwordLabel = QtGui.QLabel(self.widget)
        self.passwordLabel.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
        self.passwordLabel.setObjectName("passwordLabel")
        self.labelVerticalLayout.addWidget(self.passwordLabel)
        self.dataInputLayout.addLayout(self.labelVerticalLayout)
        self.labelButtonVerticalLayout = QtGui.QVBoxLayout()
        self.labelButtonVerticalLayout.setObjectName("labelButtonVerticalLayout")
        self.userIDLineEdit = QtGui.QLineEdit(self.widget)
        self.userIDLineEdit.setObjectName("userIDLineEdit")
        self.labelButtonVerticalLayout.addWidget(self.userIDLineEdit)
        self.passwordLineEdit = QtGui.QLineEdit(self.widget)
        self.passwordLineEdit.setObjectName("passwordLineEdit")
        self.labelButtonVerticalLayout.addWidget(self.passwordLineEdit)
        self.dataInputLayout.addLayout(self.labelButtonVerticalLayout)
        self.verticalLayout.addLayout(self.dataInputLayout)
        spacerItem = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
        self.verticalLayout.addItem(spacerItem)
        self.buttonLayout = QtGui.QHBoxLayout()
        self.buttonLayout.setObjectName("buttonLayout")
        self.newUserPushButton = QtGui.QPushButton(self.widget)
        self.newUserPushButton.setObjectName("newUserPushButton")
        self.buttonLayout.addWidget(self.newUserPushButton)
        self.loginPushButton = QtGui.QPushButton(self.widget)
        self.loginPushButton.setObjectName("loginPushButton")
        self.buttonLayout.addWidget(self.loginPushButton)
        self.verticalLayout.addLayout(self.buttonLayout)

        self.retranslateUi(LoginForm)
        QtCore.QMetaObject.connectSlotsByName(LoginForm)

        QtCore.QObject.connect(self.loginPushButton, QtCore.SIGNAL("clicked()"), self.confirmUser)

    def confirmUser(self):
        programWindow = QtGui.QDialog()
        self.fooA = 'fooA'   # these are needed in real program
        self.fooB = 'fooB'   # these are needed in real program
        programDialog = SelectProgramForm(self.fooA, self.fooB)
        programDialog.setupUi(programWindow)
        programWindow.exec_()

    def retranslateUi(self, LoginForm):
        LoginForm.setWindowTitle(QtGui.QApplication.translate("LoginForm", "Login", None, QtGui.QApplication.UnicodeUTF8))
        self.userIDLabel.setText(QtGui.QApplication.translate("LoginForm", "Username:", None, QtGui.QApplication.UnicodeUTF8))
        self.passwordLabel.setText(QtGui.QApplication.translate("LoginForm", "Password:", None, QtGui.QApplication.UnicodeUTF8))
        self.newUserPushButton.setText(QtGui.QApplication.translate("LoginForm", "New User?", None, QtGui.QApplication.UnicodeUTF8))
        self.loginPushButton.setText(QtGui.QApplication.translate("LoginForm", "Log In", None, QtGui.QApplication.UnicodeUTF8))


if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    window = QtGui.QDialog()
    newUser = LoginForm(connectionName)
    newUser.setupUi(window)
    window.show()
    sys.exit(app.exec_())

这是另一个可编译的示例,显示了我正在寻找的内容。每个窗口都可以关闭。请注意,有三个级别的窗口,一个由另一个激活,第二个和第三个窗口上没有关闭图标(又名“X”按钮)。如果只有此代码可以与其他代码一起使用...

'''
Created on 2010-06-18

@author: dhatt
'''

import sys
from PyQt4 import QtGui, QtCore

class WindowLV3(QtGui.QDialog):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)

        self.setWindowFlags(QtCore.Qt.CustomizeWindowHint|QtCore.Qt.WindowTitleHint|QtCore.Qt.WindowMaximizeButtonHint)
        self.setGeometry(300, 300, 120, 150)
        self.setWindowTitle('LV3')

        quit = QtGui.QPushButton('Close', self)
        quit.setGeometry(10, 10, 60, 35)

        self.connect(quit, QtCore.SIGNAL('clicked()'),
            self.reject)


class WindowLV2(QtGui.QDialog):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.Window3 = WindowLV3()

        self.setWindowFlags(QtCore.Qt.CustomizeWindowHint|QtCore.Qt.WindowTitleHint|QtCore.Qt.WindowMaximizeButtonHint)
        self.setGeometry(300, 300, 120, 150)
        self.setWindowTitle('LV2')

        self.quit = QtGui.QPushButton('Close', self)
        self.quit.setGeometry(10, 10, 60, 35)

        next = QtGui.QPushButton('Lv3', self)
        next.setGeometry(10, 50, 60, 35)

        self.connect(self.quit, QtCore.SIGNAL('clicked()'),
            self.reject)

        self.connect(next, QtCore.SIGNAL('clicked()'),
            self.nextWindow)

    def nextWindow(self):
        self.Window3.show()


class WindowLV1(QtGui.QDialog):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.Window2 = WindowLV2()

        self.setGeometry(300, 300, 120, 150)
        self.setWindowTitle('LV1')

        next = QtGui.QPushButton('Lv2', self)
        next.setGeometry(10, 50, 60, 35)

        quit = QtGui.QPushButton('Close', self)
        quit.setGeometry(10, 10, 60, 35)

        self.connect(next, QtCore.SIGNAL('clicked()'),
            self.nextWindow)

        self.connect(quit, QtCore.SIGNAL('clicked()'),
             self.reject)
        #QtGui.qApp, QtCore.SLOT('quit()'))

    def nextWindow(self):
        self.Window2.show()


if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    Window1 = WindowLV1()
    Window1.show()
    sys.exit(app.exec_())

狩猎愉快!

【问题讨论】:

    标签: qt4 pyqt pyqt4 signals-slots multi-window


    【解决方案1】:

    我回答了你之前的问题。这里的解决方法是一样的,只需替换

    self.connect(self.pushButtonLogout, QtCore.SIGNAL("clicked()"), self.reject)
    

    self.connect(self.pushButtonLogout, QtCore.SIGNAL("clicked()"), self.close)
    

    这应该会关闭对话框。

    【讨论】:

    • 我以前试过。我又试了一次,我得到了这个错误:“RuntimeError:底层 C/C++ 对象已被删除”也许你的 PyQt 版本与我的不同(这就是它适用于你的原因)?我正在使用:Python 2.6.5; C/C++ CDT插件4.0; PyDev 1.5.7;日食 3.5;和诺基亚的 Qt Eclipse 集成包。我使用 Linux 作为我的操作系统。
    【解决方案2】:

    我实际上并没有运行代码,但从错误来看,它似乎正在尝试访问本地对象。

    以下代码可能是问题所在:

    def confirmUser(self):
            programWindow = QtGui.QDialog()
            self.fooA = 'fooA'   # these are needed in real program
            self.fooB = 'fooB'   # these are needed in real program
            programDialog = SelectProgramForm(self.fooA, self.fooB)
            programDialog.setupUi(programWindow)
            programWindow.exec_()
    

    这里有两种可能性。 1) 将programWindow 设为实例变量。即制作self.programWindow = QtGui.QDialog()

    2) 理想情况下,您应该创建self.programWindow 的单个实例,并且可以在此处调用self.programWindow.show()。即confirmUser 中的一些代码可以移动到初始化方法中。但是我实际上并没有深入研究您的代码来说“这是正确的方法”……只是尝试一下。

    【讨论】:

    • 我很抱歉没有尽快回复,实际上几天后我什至没有阅读这篇文章就找到了解决方案,所以我没有尝试。我是新手,所以我看不出第二种可能性你来自哪里,但问题确实出在那个领域。无论如何,谢谢。
    【解决方案3】:

    我又来了,我设法找到了答案。

    我尝试切换齿轮,并改用 QWizard,但即使 QWizard 仍然存在一些与我的对话框相同的问题(RuntimeError:底层 C/C++ 对象已被删除),我又看了一下我的代码,并发现了这一点。

    我想出了一种方法,最终只使用一个对话框来关闭表单。结果发现 LoginForm 没有正确设置为 QDialog 因为它实际上是两个对象,窗口和对象本身(这不是真正的 QDialog 对象)。

    之前的代码:

    # a QDialog inside a LoginForm object (as a QDialog class), if I close this, the 'window' QDialog object is left hanging and raises an error
    window = QtGui.QDialog()
    newUser = LoginForm(connectionName)
    newUser.setupUi(window)
    window.show() code here
    

    后面的代码:

    # a LoginForm object as a QDialog class.  When closed, nothing is left hanging
    window = LoginForm(connectionName)
    window.setupUi(window)
    window.show()
    

    加上更改LoginForm类本身的几行的工作(即,将SetupUI方法完全重构出LoginForm类)

    并将其添加到类本身(LoginForm 类)

    class LoginForm(QtGui.QDialog):
    """
    This makes the LoginForm object subclassed from a QDialog object.
    """
    
    def __init__(self, parent, fooA, fooB):
        super(LoginForm, self).__init__(parent)
        # Add whatever code you want afterwards
    

    这可能不是最好的方式,但这是我设法做到的方式,而且我发现我的代码更干净,没有 SetupUI 从 QtDesigner 为我设置的所有混乱。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-15
      • 2012-09-20
      • 1970-01-01
      • 2014-10-21
      • 2010-10-27
      相关资源
      最近更新 更多