Die bockige QMessageBox

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Hallo Leute, ich habe mir mal aus Spielerei eine eigene Message-Box kreiert. Man kann zwar mit der Python hauseigene Message-Box arbeiten, aber ich war neugierig zu wissen, wie man seine Message-Box beliebig gestalten kann.

Code: Alles auswählen

from PyQt4.QtCore import *
from PyQt4.QtGui import QApplication, QMainWindow, QMessageBox, QPushButton
from PyQt4.uic import *

class Mdi_Main(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)

    def closeEvent(self, event):
        self.msgBox = QMessageBox()
        self.msgBox.setText('What to do?')
        self.msgBox.addButton(QPushButton('Accept'), QMessageBox.YesRole)
        self.msgBox.addButton(QPushButton('Reject'), QMessageBox.NoRole)
        self.msgBox.addButton(QPushButton('Cancel'), QMessageBox.RejectRole)
        self.msgBox.exec_()

        if self.msgBox == QMessageBox.YesRole:
            app.quit()
        else:
            event.ignore()


app = QApplication(sys.argv)
app.setQuitOnLastWindowClosed(False)
window = Mdi_Main()
sys.exit(app.exec_())
Beim Beenden der QMainWindow wird die closeEvent-Funktion aufgerufen. Dort ist also die selbst gebastelte Message-Box untergebracht. Beim Klick auf YesRole soll die QMainWindow geschlossen. Hier in diesem Falle muss ich mich selbst um das Schließen der QMainWindow kümmern, daher auch die app.quit()-Methode. Nun, was passiert? Ich würde sagen : Gar nichts. Nicht mal ein Fehler wird geworfen. Die QMainWindow wird nicht geschlossen. Was habe ich hier übersehen?

Besten Dank
Sophus
BlackJack

@Sophus: Du vergleichst in Zeile 17 ein Objekt vom Typ `QMessageBox` mit einer ganzen Zahl — ich hoffe das ist jetzt nicht allzu überraschend dass das niemals `True` ergibt.

Es macht keinen Sinn das `QMessageBox`-Exemplar an das Hauptfensterobjekt zu binden. Das sollte ein ganz normaler lokaler Name sein. Neue Attribute sollte man ausserhalb der `__init__()` beziehungsweise von dort aufgerufenen Methoden sowieso nicht neu einführen weil Klassen sonst recht unübersichtlich werden.

Eventuell würde ich das `event` noch akzeptieren bevor die Anwendung verlassen wird.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@BlackJack: Einige deiner Anmerkungen habe ich übernommen:

Code: Alles auswählen

    def closeEvent(self, event):
        msgBox_close = QMessageBox()
        msgBox_close.setWindowTitle("MessageBox")
        msgBox_close.setIconPixmap(QPixmap('question.png'))
        msgBox_close.setText("You want to quit it?")
        msgBox_close.addButton(QPushButton("Yes"), QMessageBox.YesRole)
        msgBox_close.addButton(QPushButton("No"), QMessageBox.NoRole)
        msgBox_close.addButton(QPushButton("Cancel"), QMessageBox.RejectRole)
        msgBox_close.exec_()

        if msgBox_close == QMessageBox.Yes:
            event.accept()
            app.quit()
        else:
            event.ignore()
Jedoch verstehe ich eine Sache nicht. Im nach folgenden Beispiel wird das Objekt reply vom Typ QMessageBox ebenso mit einer ganzen Zahl verglichen. Oder etwa nicht?
def closeEvent(self, event):
reply = QtGui.QMessageBox.question(self, 'Message',
"Are you sure to quit?", QtGui.QMessageBox.Yes,
QtGui.QMessageBox.No)

if reply == QtGui.QMessageBox.Yes:
event.accept()
else:
event.ignore()
Benutzeravatar
Madmartigan
User
Beiträge: 200
Registriert: Donnerstag 18. Juli 2013, 07:59
Wohnort: Berlin

Sophus hat geschrieben:Im nach folgenden Beispiel wird das Objekt reply vom Typ QMessageBox ebenso mit einer ganzen Zahl verglichen. Oder etwa nicht?
Nein, das ist nicht der Fall. reply "zeigt" hier auf die Funktion QMessageBox.question() oder korrekterweise auf deren Rückgabewert. In deinem Code versuchst du aber ein Objekt vom Typ QMessageBox mit QMessageBox.Yes (0x00004000) zu vergleichen. Das kann nicht funktionieren.

Die Funktion exec_() gibt dir einen Integer Rückgabewert. Diesen kannst du gegen QMessageBox.Yes usw. prüfen.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Madmartigan hat geschrieben: Die Funktion exec_() gibt dir einen Integer Rückgabewert. Diesen kannst du gegen QMessageBox.Yes usw. prüfen.
In meinem Fall meinst du die msgBox_close.exec_()-Funktion?
Denn ich frage nur, weil ich das versucht habe wie folgt zu lösen - leider ohne Erfolg.

Code: Alles auswählen

    def closeEvent(self, event):
        msgBox_close = QMessageBox()
        msgBox_close.setWindowTitle(self.set_language.dict_msgBox["msgBox_close_title"])
        msgBox_close.setIconPixmap(QPixmap(self.get_Path_msgbox_icon))
        msgBox_close.setText(self.set_language.dict_msgBox["msgBox_close_text"])
        msgBox_close.addButton(QPushButton(self.set_language.dict_msgBox["msgBox_close.yes"]), QMessageBox.YesRole)
        msgBox_close.addButton(QPushButton(self.set_language.dict_msgBox["msgBox_close.no"]), QMessageBox.NoRole)
        msgBox_close.addButton(QPushButton(self.set_language.dict_msgBox["msgBox_close.cancel"]), QMessageBox.RejectRole)
        ret = msgBox_close.exec_()

        if  ret == QMessageBox.Yes:
            event.accept()
            app.quit()
        else:
            event.ignore()
Ich habe versucht über das Objekt ret an die Funktion msgBox_close.exec_() zu gelangen, aber die gleiche Reaktion - das Fenster bleibt weiterhin offen.

Edit: Ich habe das ganze anders versucht:

Code: Alles auswählen

    def closeEvent(self, event):
        msgBox_close = QMessageBox()
        msgBox_close.setWindowTitle(self.set_language.dict_msgBox["msgBox_close_title"])
        msgBox_close.setIconPixmap(QPixmap(self.get_Path_msgbox_icon))
        msgBox_close.setText(self.set_language.dict_msgBox["msgBox_close_text"])
        msgBox_close.addButton(QPushButton(self.set_language.dict_msgBox["msgBox_close.yes"]), QMessageBox.YesRole)
        msgBox_close.addButton(QPushButton(self.set_language.dict_msgBox["msgBox_close.no"]), QMessageBox.NoRole)
        msgBox_close.addButton(QPushButton(self.set_language.dict_msgBox["msgBox_close.cancel"]), QMessageBox.RejectRole)
        ret = msgBox_close.exec_()

        if  ret == 0:
            event.accept()
            app.quit()
        else:
            event.ignore()
Ich weiß jetzt allerdings nicht, ob das nun in eurem Sinne gemeint war? Es funktioniert, frage ich lieber nochmal nach: War das so gemeint?
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

QMessageBox.Yes ist in Qt ein enum QMessageBox::StandardButton (ja das ist C++): http://qt-project.org/doc/qt-4.8/qmessa ... utton-enum
Die Methode exec_ (die in C++ exec heißt: http://qt-project.org/doc/qt-4.8/qdialog.html#exec) gibt ein enum QDialog::DialogCode (http://qt-project.org/doc/qt-4.8/qdialo ... gCode-enum) zurück.
Die Methode result (http://qt-project.org/doc/qt-4.8/qdialog.html#result) gibt Dir ein enum QMessageBox::StandardButton (http://qt-project.org/doc/qt-4.8/qmessa ... utton-enum) zurück, wenn Deine Buttons als StandardButtons angelegt wurden:

Code: Alles auswählen

import sys
from PyQt4.QtGui import QApplication, QMainWindow, QMessageBox, QPushButton
 
class Mdi_Main(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
 
    def closeEvent(self, event):
        self.msgBox = QMessageBox()
        self.msgBox.setText('What to do?')
        self.msgBox.addButton(QMessageBox.Yes)
        self.msgBox.addButton(QMessageBox.No)
        self.msgBox.addButton(QMessageBox.Ignore)
        self.msgBox.exec_()
        result = self.msgBox.result()
        if result == QMessageBox.Yes:
            app.quit()
        else:
            event.ignore()
 
app = QApplication(sys.argv)
app.setQuitOnLastWindowClosed(False)
window = Mdi_Main()
window.show()
sys.exit(app.exec_())
a fool with a tool is still a fool, www.magben.de, YouTube
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@MagBen: Besten Dank. Aber die Stand-QMessageBox mit ihren Standard-Button ist für mich nicht so interessant :-) Aber trotzdem danke für die Information, man lernt gerne was hinzu.
Antworten