2. Fenster öffnen

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
Cascoin
User
Beiträge: 24
Registriert: Dienstag 17. Mai 2011, 18:12

Hallo zusammen,

ich weiß, über Fenster gabs schon mehrere Beiträge. Aber die konnten mir nicht weiterhelfen weil die alle den Designer verwendet haben.

Naja auf jedenfall habe ich eine Frage:

Ich habe mir ein Fenster (als Klasse) erstellt. Das Fenster beinhalten 2 Buttons und einen TextEdit.

Hier der Code:

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys
import Modul_1, Modul_2
import Klasse

from PyQt4 import QtGui, QtCore



class Modul_1(QtGui.QMainWindow):  #QtGui.QWidget
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)

        self.setGeometry(200, 300, 400, 300)                #Fenstergeometrie
        self.setWindowTitle("Modul_1")


        self.Andi = Klasse.student                          # Erzeugung Student-Klasse
        self.Andi.name = "Janni"

        
        self.Ausgabe = QtGui.QTextEdit("init", self)        #Ausgabe-Fenster
        self.Ausgabe.move(70, 90)


        self.button1 = QtGui.QPushButton("Button 1", self)  # Buttons's
        self.button1.move(30, 50)

        self.button2 = QtGui.QPushButton("Button 2", self)
        self.button2.move(150, 50)

        self.button3 = QtGui.QPushButton("Button 3", self)
        self.button3.move(270, 50)


        self.statusBar().showMessage('Ready')       #Statusleiste



                                                                                    # Connections
        self.connect(self.button1, QtCore.SIGNAL('clicked()'),self.statusBar(),
                    QtCore.SLOT(self.statusBar().showMessage("ready")))

        self.connect(self.button1, QtCore.SIGNAL('clicked()'), self.buttonClicked)
        self.connect(self.button2, QtCore.SIGNAL('clicked()'), self.button2Clicked)
        
                                                                                    #neue schreibweise vgl
        self.connect(self.button1, QtCore.SIGNAL('clicked()'), self.Text1)
        self.connect(self.button2, QtCore.SIGNAL('clicked()'), self.Text2)


        self.connect(self.button3, QtCore.SIGNAL('clicked()'), self.OpenWin)
                                                                                    #SLOT Funktionen

    def OpenWin(self):
        mod_2 = Modul_1()
        

        
    def Text1(self):
        self.Ausgabe.setText("Taste 1")

    def Text2(self):
        self.Ausgabe.setText("Taste 2")

    def buttonClicked(self):
        sender = self.sender()
        self.statusBar().showMessage(sender.text() + ' was pressed')
        

    def button2Clicked(self):
        sender = self.sender()
        self.statusBar().showMessage(sender.text() + ' was pressed')
        

        

    def receive_klick(self):
        sender = self.sender()
        QtCore.SLOT(self.Ausgabe.setText("Output"))

Ich möchte momentan Signal & Slots verstehen. Daher habe ich zur Übung versucht, durch drücken des Button_3 ein neues Fenster zu öffnen.
Das neue Fenster ist wieder dieselbe Klasse.
Über diese Funktion wollte ich mir eine neue Instanz derselben Klasse erzeugen. Diese Instanz heißt dann eben mod_2

Code: Alles auswählen

    def OpenWin(self):
        mod_2 = Modul_1()

Den "connect" Befehl habe ich so angewendet:

Code: Alles auswählen

        self.connect(self.button3, QtCore.SIGNAL('clicked()'), self.OpenWin)
Es kommt zwar keine Fehlermeldung, aber funktionieren tuts auch nicht.

Also warum? Wo liegt der Fehler? Ich kenne mich mit Objektorientierung eigneltich kaum aus muss ich zugeben....
Das meine connect-Schreibweise veraltet ist ist mir im übrigen klar. Ich will aber erstmal den gröbsten Fehler ausmerzen und das Programm dazu bringen das zu tun was ich möchte.

Falls mir jemand helfen könnte wäre das toll.

Gruß

Cascoin
Cascoin
User
Beiträge: 24
Registriert: Dienstag 17. Mai 2011, 18:12

Hab den ersten Fehler gefunden....
Hier der Code...

Code: Alles auswählen

def OpenWin(self):
        mod_2 = Modul_1()
        mod_2.show()          ####Neu reingemacht
Jetzt öffnet sich ein neues Fenster wie gewollt.... Nur schließt es sich sofort wieder....
Die Frage ist wieso... Hat wohl irgendetwas mit dem Konstruktor zu tun.... Nur wüßte ich nicht wie ich es sonst machen sollte...
Weil ja die Funktion OpenWin(self): gar nicht im Konstruktor steht sondern nur der connect Befehl......

bis dann

cascoin
BlackJack

@Cascoin: Das Objekt wird in der Funktion erstellt und an den lokalen Namen `mod_2` gebunden. Dann endet die Funktion, der Name existiert nicht mehr und damit kann dann auch das Objekt beseitigt werden. Du müsstest schon dafür Sorgen, dass das Objekt auch noch irgendwie erreichbar ist, damit es auf der Python-Seite nicht zerstört wird. Und damit die Speicherverwaltung auf Qt-Seite ordentlich funktioniert, solltest Du Widgets immer ein `parent` geben, damit auch Qt weiss wann die C++-Objekte zerstört werden können.

Die Namensgebebung ist nicht so toll. Du nennst eine Klasse `Modul_1` und ein Modul nennst Du `Klasse`. Da ist Verwirrung vorprogrammiert.

``Klasse.student`` macht sicher nicht das was der Kommentar an der Stelle sagt. Zum einen sollte im Kommentar wahrscheinlich stehen das ein Student-*Exemplar* erstellt wird und keine Klasse und dann wird ja nur das Objekt `Klasse.student` an das Attribut `Andi` gebunden. Da wird nichts neues erstellt. Beide Namen beziehen sich auf das *selbe* Objekt.

GUIs sollten mit Layouts gestaltet werden und nicht in dem man Elemente an absolute Positionen verschiebt. Das kann wenn man Glück hat bei anderen nur besch…eiden aussehen — wenn man kein Glück hat werden GUIs auf diese Weise unbenutzbar.
Cascoin
User
Beiträge: 24
Registriert: Dienstag 17. Mai 2011, 18:12

ah ja klar.... Jetzt verstehe ich das sich das Fenster sofort wieder schließt.... Aber wie soll ich es sonst machen???

Das erste Fenster habe ich ja in der "Hauptroutine" aufgerufen.

Code: Alles auswählen

app = QtGui.QApplication(sys.argv)

START = Modul_1()
START.show()
sys.exit(app.exec_())
Daher macht es auch Sinn das sich das erste Fenster nicht wieder schließt, das erste schon....

Hat jemand einen Tipp wie ich das machen könnte? Ich mag keinen Code, sondern nur was ich wo hinschreiben müßte....
Danke auch für die restlichen Infos.... Einiges habe ich registriert und werde das klarer darstellen....

Jedoch dachte ich das wenigsten dieser Code-Teil stimmt:

Code: Alles auswählen

        self.Andi = Klasse.student                          # Erzeugung Student-Klasse
        self.Andi.name = "Janni"
Und zwar wurde hier aus einem anderen Modul (das Modul habe ich Klasse genannt -> sorry für die Verwirrung) eine Instanz der Klasse Student erzeugt. Diese Klasse hat ein Attribut name, dem ich dem Wert "Janni" zugewiesen habe....
So war es zumindest gedacht.... Allerdings erzeuge ich auch diese Instanz im Konstruktor. Gelöscht wird diese Instanz aber nicht nachdem der Konstruktor beendet wird.... Versteh ich auch nicht.... Ist aber so, habs ausprobiert....

Naja, also wie ich ein zweites Fenster erzeugen könnte ohne das es gleich wieder verschwindet ist meine primäre Frage.....

vielen Dank

Cascoin
BlackJack

@Cascoin: Du müsstest halt dafür sorgen dass Du auch weiterhin an das Fensterobjekt kommen kannst. Zum Beispiel in dem Du sie in eine Datenstruktur steckst. Ein einfaches Attribut würde wohl nicht gehen, denn dann müsstest Du verhindern dass die Methode mehr als einmal aufgerufen wird und das Attribut an ein weiteres Fenster binden kann.

Vielleicht stimmt ja der Code mit dem Studenten, aber er passt nicht zum Kommentar. Da wird nichts erzeugt. Wenn die Klasse `Student` heisst, nehme ich mal an, dass das Exemplar in dem Modul `Klasse` erzeugt und dort an den Namen `student` gebunden wird!? Und dann hätte wohl das Exemplar ein Attribut `name` und nicht die Klasse!? Den zweiten Absatz der Erklärung verstehe ich gar nicht. Von welchem Konstruktor reden wir jetzt?
Cascoin
User
Beiträge: 24
Registriert: Dienstag 17. Mai 2011, 18:12

Hi BlackJack,

dank dir für deine Hilfe..... Habe es hinbekommen....

Als Lösung habe ich einfach eine zweite Instanz meiner Fensterklasse im Konstruktor (der anderen Instanz der Fensterklasse) geöffnet und mit meinem Knopf schalte ich es entweder auf .show() oder auf .hide()..... So klappt es zumindestens.....

Naja, das wo du nicht verstanden hast (in meinem obrigen Beitrag) vergiss auch bitte ganz schnell.... Wenn du wüßtest was ich mir dabei gedacht habe würdest du mich schlagen....haha....
Naja, der Kommentar war (ist korrigiert) wie du sagtest irreführend/falsch....

Dann einen schönen Abend...

Cascoin
Antworten