Widget, Main Window, Dialog?

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
LenardZill
User
Beiträge: 5
Registriert: Mittwoch 22. Mai 2013, 09:36

Moin an alle,

Ich habe grade neu in Pyqt angefangen und frage mich jetzt wo der Unterschied zwischen Widget, Main Window und Dialog ist.
Mit anderen Worten, wann verwende ich was bzw. was sind die vor- nachteile?

Ausserdem möchte ich gerne von einem Fenster ein anderes öffnen.
Ich habe also eine ausgangsdatei "main.py" von der öffne ich das Fenster und warte bis die eingabe getätigt wurde.
Jetzt möchte ich das nächste Fenster öffnen weiß aber nicht wie ich das anstellen sollte.

Danke schonmal für eure Antworten! :)
Gruß Lenard

PS: Hier einmal wie ich das erste Fenster aufrufe:

Code: Alles auswählen

import sys
from PyQt4 import QtGui, QtCore
from dialog.main import Ui_MainForm as Frm

class Main(QtGui.QWidget, Frm):
    
    def __init__(self, nutzername):
        QtGui.QWidget.__init__(self)
        self.setupUi(self)

app = QtGui.QApplication(sys.argv) 
widget = Main()
widget.show()
sys.exit(app.exec_())
Zuletzt geändert von Anonymous am Mittwoch 22. Mai 2013, 10:00, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
BlackJack

@LenardZill: Verwendung: `QMainWindow` für das Hauptfenster, `QDialog` für Dialoge, und `QWidget` für Fenster die weder Hauptfenster noch Dialog sind und für die es keine passendere, spezialisierte Klasse gibt. Was die Klassen jeweils bieten und wofür man sie einsetzt steht in der Qt-Dokumentation zu diesen Klassen ziemlich ausführlich beschrieben.

Für Dein Code-Beispiel müsstest Du den Signal/Slot-Mechanismus von Qt verwenden um auf die Benutzereingabe zu reagieren und das nächste Fenster zu öffnen. Also irgendein passendes Signal mit einer Funktion oder Methode verbinden, welche dann das nächste Fenster öffnet.

*So* wird das übrigens nicht funktionieren, denn Dein `Main.__init__()` erwartet ein Argument, welches Du aber beim Aufruf gar nicht übergibst.

Das ``as`` beim Import ist übrigens unschön. Abkürzungen sollte man vermeiden, solange sie nicht allgemein bekannt sind. Ich sehe hier den Sinn auch nicht so ganz. Man kürzt mit ``as`` in ein paar Fällen einen Namen ab, wenn man den wirklich sehr oft benötigt, aber dieses `Frm` wird im weiteren Quelltext nur ein einziges mal verwendet. Da hat man also überhaupt keinen Gewinn von, das man den Quelltext unleserlicher macht.

Mit `PyQt4` würde ich ausserdem keinen generierten Quelltext verwenden. Diese Qt-Anbindung hat ein Modul mit dem Namen `PyQt4.uic` mit dem man die GUI-Daten zur Laufzeit einlesen und in Objekte umwandeln kann. Damit spart man sich den Zwischenschritt der Quelltextgenerierung und auch etwas „Boilerplate”-Quelltext. Dein Quelltext könnte dann ungefähr so aussehen:

Code: Alles auswählen

import sys
from PyQt4 import QtGui, uic


def main():
    app = QtGui.QApplication(sys.argv) 
    widget = uic.loadUi('main_form.ui')
    widget.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()
Man kann `loadUi()` auch eine Qt-Klasse (oder eine davon abgeleitete) mitgeben, von der dann ein Exemplar erstellt wird und das UI dann „darin” erstellt wird, um einen ähnlichen Effekt wie den von Deinem Klassenbeispiel zu bekommen.
LenardZill
User
Beiträge: 5
Registriert: Mittwoch 22. Mai 2013, 09:36

Vielen Dank schonmal für die Erklärung und richtigstellung meines Codes.

Zu dem Signal/Slot-Mechanismus hab ich jetzt noch eine frage. Wie bekomme ich jetzt das Signal vom Button abgefangen.
Vorher ging es ja mit:

Code: Alles auswählen

self.connect(self.button, QtCore.SIGNAL('pressed()'), self.openWindow())

Gruß
Lenard
BlackJack

@LenardZill: *So* ging das vorher nicht, denn als letztes Argument wird etwas aufrufbares erwartet. Du übergibst da aber den *Rückgabewert* von der `openWindow()`-Methode und nicht die Methode *selbst*. Du sollst die ja zu dem Zeitpunkt nicht aufrufen, sondern Qt soll die später aufrufen wenn jemand auf die Schaltfläche klickt.

Heutzutage sollte man ausserdem nicht mehr diese Form des Verbindens verwenden. Die Signale gibt es als Attribute auf den Objekten und die haben eine `connect()`-Methode. Ausserdem würde ich `clicked` und nicht `pressed` verwenden. Das dürfte sich dann eher so verhalten, wie der Benutzer das erwartet.

Wie gesagt, man kann der `loadUi()`-Funktion ein zweites Argument mitgeben, in welches dann die GUI „geladen” wird. Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python
import sys
from PyQt4 import QtGui, uic


class Main(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        uic.loadUi('main_form.ui', self)

        # self.connect(self.button, QtCore.SIGNAL('pressed()'), self.openWindow)
        self.button.clicked.connect(self.openWindow)

    def openWindow(self):
        pass


def main():
    app = QtGui.QApplication(sys.argv) 
    widget = Main()
    widget.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()
LenardZill
User
Beiträge: 5
Registriert: Mittwoch 22. Mai 2013, 09:36

Achso, jetzt wird es mir klar.

Hab jetzt alles umgesetzt bekommen, danke.
Aber mein letztes Problem steht noch aus, wie kann ich jetzt einen anderen Dialog öffnen?

Code: Alles auswählen

import sys
import ProdukteGui
from PyQt4 import QtGui, uic

class Main(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QDialog.__init__(self)
        uic.loadUi('ui\main.ui')
        
        self.buttonBestellung.clicked.connect(self.openWindow)
        
    def openWindow(self):
        #Hier jetzt ein anderes Fenster oeffnen
        produkteGui = ProdukteGui.main
        produkteGui.show()
        
def main():
    app = QtGui.QApplication(sys.argv)
    window = Main()
    window.show()
    sys.exit(app.exec_())
    
if __name__ == '__main__':
    main()
Die ProdukteGui ist gleich aufgebaut.

#Gruß Lenard
BlackJack

@LenardZill: Wenn Du mit gleich aufgebaut meinst die hat auch eine `main()`-Funktion in der ein Exemplar von `QApplication` erstellt und dessen `exec_()`-Methode aufgerufen wird, dann geht das nicht. Lies Dir dazu mal die Beschreibung von `QApplication` in der Qt-Dokumentation durch. Der dritte Absatz ist da sehr deutlich.

Du musst halt von der anderen GUI-Klasse ein Exemplar erstellen und dort die `show()`-Methode drauf aufrufen.
EmaNymton
User
Beiträge: 174
Registriert: Sonntag 30. Mai 2010, 14:07

Vielleicht wäre es auch sinnvoll, wenn du mal beschreibst, was du genau mit dem "Dialog" bezwecken willst. Ich habe nämlich den Eindruck, dass du QMainWindows, QWidgets und QDialoge durcheinander wirfst.

Qt hat z.B. für Standarddialoge, also z.B. simple Abfragen für Strings, Zahlen, ... schon vorgefertigte Klassen, die man verwenden kann. Da musst du nicht das Rad neu erfinden. Wenn du einen eigenen Dialog brauchst, solltest du, wie BlackJack bereits angedeutet hat, ein Objekt der Klasse QDialog erstellen und die Oberfläche halt deinen Bedürfnissen anpassen.
LenardZill
User
Beiträge: 5
Registriert: Mittwoch 22. Mai 2013, 09:36

@EmaNymton: warscheinlich würfel ich wirklich was durcheinander..

Meine Dialoge sind einfach ein weiteres Fenster was sich öffnet. Bsp. Einstellungen.
Oder nehme ich für soetwas lieber QWidgets?
BlackJack

@LenardZill: Das kommt halt darauf an ob Du etwas brauchst was die Dialog-Klassen bieten. Ich verweise noch einmal auf die Qt-Dokumentation. Da steht bei `QDialog` ausführlich worin die sich von `QWidget` unterscheiden.
LenardZill
User
Beiträge: 5
Registriert: Mittwoch 22. Mai 2013, 09:36

So, ich hab mir jetzt die QT Dokumentation zum besten gegeben und hoffe ich hab's nun richtig.
Vielen Dank für den Support euch beiden!.

#Gruß Lenard
Antworten