2010-06-19 7 views
1

J'ai un autre problème avec PyQT, cette fois j'ai un exemple qui sera beaucoup plus utile car il contient une partie de mon code (défendu bien sûr!) I avoir du mal à trouver comment fermer la boîte de dialogue 'PROGRAM SELECT' en utilisant seulement le bouton 'LOGOUT'. Je pourrais simplement utiliser le bouton de fermeture sur le formulaire, mais je veux le faire avec le bouton 'LOGOUT'.Multi-programme de dialogue dans PyQT ne se ferme pas (la suite!)

Quelqu'un pourrait-il m'aider à résoudre ce problème?

Voici un code compilable pour vous tous à mâcher.

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

Voici un autre exemple compilable qui montre ce que je cherche. Chaque fenêtre est capable de se fermer. Notez qu'il existe trois niveaux de fenêtres, l'un activé par l'autre, qu'il n'y a pas d'icônes de fermeture (les boutons 'X') sur les deuxième et troisième fenêtres. Si seulement ce code fonctionnerait avec l'autre code ...

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

Bonne chasse!

Répondre

0

Je suis encore là, et j'ai réussi à trouver une réponse. J'ai essayé de changer de vitesse, et en utilisant un QWizard à la place, mais quand même QWizard avait encore les mêmes problèmes que ceux de mes dialogues (RuntimeError: l'objet C/C++ sous-jacent a été supprimé), j'ai jeté un coup d'oeil mon code, et l'ai découvert.

J'ai trouvé un moyen de finalement fermer les formulaires en utilisant simplement un dialogue. Il s'avère que le LoginForm n'a pas été configuré correctement en tant que QDialog car il s'agit en réalité de deux objets, la fenêtre et l'objet lui-même (ce qui n'est pas un vrai objet QDialog).

Le code avant:

# 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 

Le code après:

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

Ajoutez à cela le travail de changer plusieurs lignes dans la classe LoginForm lui-même (à savoir refactoring la méthode setupUi de la Classe LoginForm entièrement)

Et ajouter cela à la classe elle-même (la classe 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 

Ce n'est peut-être pas le meilleur moyen, mais c'est ainsi que j'ai réussi à le faire, et je trouve que mon code est plus propre sans tout le désordre que SetupUI a créé pour moi depuis QtDesigner.

0

J'ai répondu à votre question précédente. La solution est ici la même chose, il suffit de remplacer

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

avec

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

Cela devrait fermer la boîte de dialogue.

+0

J'ai déjà essayé ça. J'ai encore essayé, et j'ai eu cette erreur: "RuntimeError: objet C/C++ sous-jacent a été supprimé" Peut-être que votre version de PyQt est différente de la mienne (qui est pourquoi cela fonctionne pour vous)? J'utilise: Python 2.6.5; C/C++ CDT Plugin 4.0; PyDev 1.5.7; Eclipse 3.5; et le package d'intégration Qt Eclipse de Nokia. J'utilise Linux comme mon OS. –

0

Je n'ai pas réellement exécuté le code, mais de l'erreur, il semble qu'il essaie d'accéder à un objet local.

Le code suivant pourrait être la question:

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

Il y a deux possibilités. 1) Faites programWindow en tant que variable d'instance. 2) Dans l'idéal, vous devez créer une seule instance de self.programWindow et appeler simplement self.programWindow.show() ici. c'est-à-dire qu'une partie du code de confirmUser peut être déplacée vers la méthode d'initialisation. Mais je n'ai pas étudié votre code en profondeur pour dire "c'est la bonne façon" ... essayez-le.

+0

Je m'excuse de ne pas avoir répondu plus tôt, en réalité, j'ai trouvé une solution quelques jours plus tard sans même lire ceci, donc je ne l'ai pas essayé. Je suis nouveau à cela, donc je ne vois pas d'où vous venez pour la deuxième possibilité, mais le problème résidait dans ce domaine. Merci quand même. –

Questions connexes