Aufruf von QWidgets in Klassen-Methoden

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
mephisto-online
User
Beiträge: 167
Registriert: Sonntag 29. September 2013, 17:05

Hallo, ich trau mich noch mal,

erstmal, ein Ausschnitt aus meinem Programm als Grundlage (ich hoffe, ich habe es ohne Fehler runtergekürzt !):

Code: Alles auswählen

# -*- coding: utf-8 -*-

import sys
from PyQt4 import QtGui
from mainwindow import Ui_MainWindow

import editdata as edw    # QWidget


class MainWindow(QtGui.QMainWindow):

    def __init__(self):
        super(MainWindow, self).__init__()
        self.current_base_data = 0
        ...
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.show()

    def action_of_new_button(self):    # Slot in Ui_MainWindow 
        edit_widget = ed.EditData()      # QWidget in Modul editdata=ed

    ...
        
def main():
    app = QtGui.QApplication(sys.argv)
    ex = MainWindow()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()
Weil edit_widget lokal ist in action_of_new_button(), erscheint das Widget nicht. Ich habe aber 3 andere Wege gefunden, wie es funktioniert:

Weg Nr. 1:
lokale Variable edit_widget global definiert:

Code: Alles auswählen

        global edit_widget
        edit_widget = ed.EditData()
Das funktioniert fehlerfrei.

Weg Nr. 2:
Ich mache edit_widget zum Instanz-Attribut:

Code: Alles auswählen

 self.edit_widget = ed.EditData()
Das gibt Mecker vom Meister (PyCharm): "Instanz-Attribut ausserhalb von ___init___() definiert". Das darf man wohl nicht, funzt aber.

Weg 3:
Ich definiere edit_widget global in der Klassen-Definition:

Code: Alles auswählen

class MainWindow(QtGui.QMainWindow):

    edit_widget = QObject
    ... 
    def __init__(self):
    ...
    def action_of_new_button(self):   
        edit_widget = ed.EditData()      
Das habe ich so nirgens gelesen, mir war nur QObject eingefallen und da dachte ich, so könnte es gehen. Und es funktioniert ebenfalls fehlerfrei.

Nur weiss ich jetzt nicht, wie man es richtig macht. Die QObject-Methode erscheint mir am sinnvollsten ? Wenn das richtig ist, hätte ich dann direkt noch eine Frage: gibt es im "normalen" Python auch so etwas wie das QObject in Qt ?

Freundliche Grüße
mephisto-online

P.S.: Wenn noch irgend etwas mit meiner "Python-Terminologie" nicht stimmt oder unverständlich ist, bitte ich um Korrektur.
Zuletzt geändert von mephisto-online am Dienstag 28. Januar 2014, 19:10, insgesamt 1-mal geändert.
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

@mephisto-online: Weg 3 funktioniert nicht, Weg 1 ist schlecht und Weg 2 ist der einzig richtige. Was da wirklich willst, kann ich aber aus Deinem Code nicht erraten.
mephisto-online
User
Beiträge: 167
Registriert: Sonntag 29. September 2013, 17:05

Ich möchte in einem QWindow-Objekt ein QWidget-Objekt in einer Methode erzeugen. Und das kommt wirklich nicht rüber ? :(

Weg 3 funktioniert aber ! Und bei Weg 2 gibt es eine Warnung in PyCharm ("Instance attribute edit_widget defined outside __init__!"). Ist das dann wirklich der richtige Weg ?
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

@mephisto-online: Du hast nicht erklärt, warum Du ein QWidget nachträglich erzeugen willst. Natürlich sollten die Attribute in __init__ auf None gesetzt werden. Und Weg 3 macht nicht das, was Du denkst, was da passiert. » edit_widget« innerhalb der Funktion hat mit »edit_widget« auf Klassenebene nichts zu tun. Auch hat es wenig Sinn, eine Klasse an ein Klassenattribut zu binden.
Im Übrigen sollte »show« nicht innerhalb von »__init__« aufgerufen werden, weil das Erzeugen eines Objekts nichts mit dessen Darstellung zu tun hat.
mephisto-online
User
Beiträge: 167
Registriert: Sonntag 29. September 2013, 17:05

Sirius3 hat geschrieben:Du hast nicht erklärt, warum Du ein QWidget nachträglich erzeugen willst.
Es gibt ein MainWindow(), was mein Haupt-Fenster ist, was auch, bis ich das Programm beende, immer vorhanden ist. Von hier aus möchte ich zur Eingabe oder Änderung von Daten ein 2. Fenster öffnen, die Daten dort ändern und dann wieder schliessen, die geänderten Daten entweder verwerfen (Abbrechen-Button) oder an mein Main-Window-Objekt zurückgeben (OK-Button). Dieses Fenster (Qwidget-Objekt) brauche ich dann erst mal nicht mehr und es muss auch nicht mehr darauf zugreifen.
Es geht mir aber hier nicht um die Daten. Das ist in meinem Programm-Ausschnitt auch nicht enthalten. Soll jetzt nur verdeutlichen, was ich machen möchte.
Sirius3 hat geschrieben:Natürlich sollten die Attribute in __init__ auf None gesetzt werden.
Das ist ja schon die Antwort: Definieren und den Wert None zuweisen ! Danke ! None wurde bislang in den Tuts, die ich durchgearbeitet habe, noch nicht explizit behandelt oder beschrieben, wozu man es in Python benutzen kann. Ich hatte es nur öfters schon gesehen und mir nichts weiter dabei gedacht. In statischen Sprachen ist der Inhalt "none" einer Variablen eigentlich immer igitt !
Sirius3 hat geschrieben:Und Weg 3 macht nicht das, was Du denkst, was da passiert. » edit_widget« innerhalb der Funktion hat mit »edit_widget« auf Klassenebene nichts zu tun.
Das habe ich eigentlich auch schon geahnt. Ich wusste nur nicht, wie man eine Instanz-Variable definiert, aber noch nicht zuweist.
Sirius3 hat geschrieben:Auch hat es wenig Sinn, eine Klasse an ein Klassenattribut zu binden.
Ist mir jetzt endlich :oops: sonnenklar !
Sirius3 hat geschrieben:Im Übrigen sollte »show« nicht innerhalb von »__init__« aufgerufen werden, weil das Erzeugen eines Objekts nichts mit dessen Darstellung zu tun hat.
Das ist mir schon klar ! In meinem Fall, wo es im ganzen Programm nur ein MainWindow-Objekt gibt, kann man es doch aber doch ruhig so machen, oder ? Man kann show() natürlich auch in der main() aufrufen.

Danke nochmal ! Hat mir sehr geholfen ! :D
Antworten