PyQT中的多对话框程序不会关闭(续集!)

时间:2010-06-19 00:00:43

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

我对PyQT有另一个问题,这次我有一个更有用的例子,因为它包含我的代码的一部分(当然是默认的!)我很难弄清楚如何关闭'PROGRAM SELECT'只使用“LOGOUT”按钮对话框窗口。我可以简单地使用表单上的关闭按钮,但我想用“LOGOUT”按钮来完成它。

有人能帮我解决这个难题吗?

以下是一些可编辑的代码供大家咀嚼。

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_())

快乐狩猎!

3 个答案:

答案 0 :(得分:0)

我回答了你之前的问题。这里的解决方案是相同的,只需替换

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

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

这应关闭对话框。

答案 1 :(得分:0)

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

以下代码可能是问题:

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作为实例变量。即make self.programWindow = QtGui.QDialog()

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

答案 2 :(得分:0)

我又回到了这里,我设法抓住了答案。

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

我找到了一种方法,最终只使用对话框关闭表单。原来LoginForm没有正确设置为QDialog,因为它实际上是两个对象,窗口和对象iteself(这不是真正的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类本身中添加更改几行的工作(即,完全从LoginForm类重构SetupUI方法)

并将其添加到类本身(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为我设置的所有混乱。