Hallo
mein Programm besteht nun aus mehreren QWidgets innerhalb des MainWindows
jedes QWidget erhält Buttons, LineEdits etc
Wenn ich jetzt von einem Widget ins andere wechsel, bleiben die zuvor geladenen Buttons bestehen und werden auch im neuen Widget angezeigt.
Wie krieg ich die weg? Gibt es da eine destroy Methode etc?
(button.destroy() oder ähnlich)
Widget ausblenden/beenden
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Ich weiß nicht genau, was Du da machst, aber generell gibt es Methoden wie show() und hide().
Eigentlich ist es eher unüblich, ständig neue UI-Elemente zu erzeugen, sondern man nutzt die einmal erstellten und füttert sie ggf. mit neueren / aktuellen Werten.
Du kannst Objekte natürlich (implizit) löschen, dazu gibt es das "del"-Statement:
Der Name "a" wird durch del gelöscht, das Objekt dahinter dann vom Garbage-Collector. D.h. Du hast keinen Einfluss darauf, wann das passiert!
Aber beachte:
Das Listen-Objekt ist noch an den Namen "b" gebunden, daher wird das Objekt vom Interpreter nicht gelöscht.
Ich glaube ehrlich gesagt, Du suchst etwas ganz anderes, als ständig Widgets und UI-Elemente zu generieren und wieder zu löschen. Evtl. sind TabWidgets, StackWidgets usw. etwas für Dich?
Eigentlich ist es eher unüblich, ständig neue UI-Elemente zu erzeugen, sondern man nutzt die einmal erstellten und füttert sie ggf. mit neueren / aktuellen Werten.
Du kannst Objekte natürlich (implizit) löschen, dazu gibt es das "del"-Statement:
Code: Alles auswählen
In [1]: a = 43
In [2]: del a
In [3]: a
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
C:\Dokumente und Einstellungen\nelson\Eigene Dateien\<ipython console> in <modul
e>()
NameError: name 'a' is not defined
Aber beachte:
Code: Alles auswählen
In [4]: a = range(10)
In [5]: b = a
In [6]: del a
In [7]: b
Out[7]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Ich glaube ehrlich gesagt, Du suchst etwas ganz anderes, als ständig Widgets und UI-Elemente zu generieren und wieder zu löschen. Evtl. sind TabWidgets, StackWidgets usw. etwas für Dich?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
Hier mal der Code:
Nach dem Start sehe ich 3 Buttons, New Group, Edit Groups, Delete Groups
Klicke ich auf New Group, werden 2 LineEdits und 2 Labels erzeugt
wechsel ich dann nach Edit Groups, bleiben diese Inhalte bestehen, und das möchte ich eigentlich nicht
Was mich auch ein bischen stutzig macht ist, dass die 3 Buttons in jedem Widget angezeigt werden, obwohl sie eigentlich nur im QMainWindow sichtbar sein sollten
Code: Alles auswählen
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtCore, QtGui
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
#Window description
self.resize(800, 400)
self.setWindowTitle(str('Happy Birthday'))
#Menupoints description
exit = QtGui.QAction('Quit', self)
settings = QtGui.QAction("Settings", self)
help2 = QtGui.QAction("Help", self)
about = QtGui.QAction("About",self)
#menu creation
menubar = self.menuBar()
file = menubar.addMenu('&Options')
file.addAction(settings)
file.addAction(help2)
file.addAction(about)
file.addAction(exit)
#Button function
settings.triggered.connect(self.settingsm)
exit.triggered.connect(self.close)
about.triggered.connect(self.about)
help2.triggered.connect(self.help2)
#back.triggered.connect(self.__init__)
#Pushbuttons
newgrp=QtGui.QPushButton(self)
newgrp.setText("New group")
newgrp.setGeometry(100, 300, 150, 100)
edit=QtGui.QPushButton(self)
edit.setText("Edit group")
edit.setGeometry(300, 300, 150, 100)
delgrp=QtGui.QPushButton(self)
delgrp.setText("Delete group")
delgrp.setGeometry(500, 300, 150, 100)
#Button Slots
newgrp.clicked.connect(self.newgrp)
edit.clicked.connect(self.edgrp)
delgrp.clicked.connect(self.delgrp)
def newgrp(self):
self.newgrp = QtGui.QWidget(self)
self.setWindowTitle("New group")
self.resize(800,400)
name=QtGui.QLabel(self)
name.setText("Groupname:")
name.setGeometry(10,10,200,50)
grpname=QtGui.QLineEdit(self)
grpname.setGeometry(180,10,200,50)
dialname=QtGui.QLabel(self)
dialname.setText("Dialing number:")
dialname.setGeometry(10,50,200,50)
dialed=QtGui.QLineEdit(self)
dialed.setGeometry(180,50,200,50)
add=QtGui.QPushButton(self)
add.setText("Add")
add.setGeometry(400,50,100,50)
add.show()
dialed.show()
dialname.show()
grpname.show()
name.show()
def edgrp(self):
self.edgrp = QtGui.QWidget(self)
self.setWindowTitle("Edit group")
self.resize(800,400)
def delgrp(self):
self.delgrp = QtGui.QWidget(self)
self.setWindowTitle("Delete group")
self.resize(800,400)
table=QtGui.QComboBox(self)
table.setGeometry(50,50,200,200)
delbut=QtGui.QPushButton(self)
delbut.setText("Delete")
delbut.setGeometry(50,20,100,50)
delbut.show
# table.show()
def settingsm(self):
self.settingsm = QtGui.QWidget(self)
self.setWindowTitle("Settings")
self.resize(800,400)
exit = QtGui.QPushButton("Exit",self)
exit.clicked.connect(self.close)
exit.setGeometry(100,100,100,100)
#back = QtGui.QPushButton("Back",self)
#back.clicked.connect(self.exit)
exit.show()
#back.show()
#self.settingsm.show()
def help2(self):
QtGui.QMessageBox.information(self, "Introduction:\n",
"1.Create a new group for example:\n"
"Girls or Boys. Friends or business partners\n"
"2.Chose the dialing numbers, you wish to use\n"
"3.Create your own unpersonal greeting message\n"
"4.Save your group")
def about(self):
QtGui.QMessageBox.about(self, "About",
"sfdafefawegwa<gweg .")
app = QtGui.QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())
Klicke ich auf New Group, werden 2 LineEdits und 2 Labels erzeugt
wechsel ich dann nach Edit Groups, bleiben diese Inhalte bestehen, und das möchte ich eigentlich nicht
Was mich auch ein bischen stutzig macht ist, dass die 3 Buttons in jedem Widget angezeigt werden, obwohl sie eigentlich nur im QMainWindow sichtbar sein sollten
@Robokopp: Vergiss am besten erst einmal, dass es `setGeometry()` gibt. Widgets werden mit Layouts platziert.
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Ich glaube Du hast ein paar Verständnisprobleme bezüglich Widgets. Bettest Du ein QWidet in ein anderes, so bekommt es natürlich keinen Window-Titel u.ä.. Nur der "Inhalt" wird dargestellt. Außerdem musst Du Dich um das Ein- bzw. Ausblenden selber kümmern (s. show() und hide()).
hinzu kommt das imho eigentümliche UI-Design an sich. Du benötigst doch irgend einen Datentypen ("Gruppe"?), der die Daten hält, die Du da verwalten willst. Imho ist das also ein Fall für ein Modell, welches Du dann in einem Container-Widget wie einem QListView anzeigen lässt. Daneben gibt es dann idR Felder für die Details, die beim Anklicken eines Items in dem View angezeigt wird. Daneben kann es dann noch die Buttons geben, die Du da bisher "global" im MainWindow stehen hast.
Ich habe mal ein kleines Demo-UI mit dem Designer zusammengeklickt:

Und hier der ui-Code:
UI-File
Natürlich habe ich hier das nicht modellbasierte QListWidget gewählt, damit ich im Test Einträge anlegen könnte. Das sollte man dann gegen ein QListView mit passendem Modell austauschen.
hinzu kommt das imho eigentümliche UI-Design an sich. Du benötigst doch irgend einen Datentypen ("Gruppe"?), der die Daten hält, die Du da verwalten willst. Imho ist das also ein Fall für ein Modell, welches Du dann in einem Container-Widget wie einem QListView anzeigen lässt. Daneben gibt es dann idR Felder für die Details, die beim Anklicken eines Items in dem View angezeigt wird. Daneben kann es dann noch die Buttons geben, die Du da bisher "global" im MainWindow stehen hast.
Ich habe mal ein kleines Demo-UI mit dem Designer zusammengeklickt:

Und hier der ui-Code:
UI-File
Natürlich habe ich hier das nicht modellbasierte QListWidget gewählt, damit ich im Test Einträge anlegen könnte. Das sollte man dann gegen ein QListView mit passendem Modell austauschen.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
Ich versteh grad garnix mehr
Der WindowTitel wird aber angezeigt.
Genau, das ein und ausbetten ist ja das wo ich hänge
ich müsste die Buttons bzw das ganze zuvor aufgerufene Widget ausbetten und ich hab keine Ahnung wie.
Wie muss ich diese Datentypen definieren?
Wiegesagt, ich hab noch keinen Bezug zu den UI Files und ich weiß nicht, wie sie arbeiten, weswegen ich damit nicht wirklich was anfangen kann
Der WindowTitel wird aber angezeigt.
Genau, das ein und ausbetten ist ja das wo ich hänge
ich müsste die Buttons bzw das ganze zuvor aufgerufene Widget ausbetten und ich hab keine Ahnung wie.
Wie muss ich diese Datentypen definieren?
Wiegesagt, ich hab noch keinen Bezug zu den UI Files und ich weiß nicht, wie sie arbeiten, weswegen ich damit nicht wirklich was anfangen kann
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Ich vermute einfach mal, das liegt daran, dass es hier ziemlich viele XY-Probleme gibtRobokopp hat geschrieben:Ich versteh grad garnix mehr

Stimmt, mein Fehler.Robokopp hat geschrieben: Der WindowTitel wird aber angezeigt.
Naja, indem Du eben je nach Button-Druck ein show() bzw. hide() für das entsprechende Widgets aufrufst.Robokopp hat geschrieben: Genau, das ein und ausbetten ist ja das wo ich hänge
ich müsste die Buttons bzw das ganze zuvor aufgerufene Widget ausbetten und ich hab keine Ahnung wie.
Dazu gibt es einen Leitfaden zur Model-View-Controller-Programmierung. Ich weiß nicht, ob Riverbank dazu etwas eigenes bei ihrer PyQt-Doku hat, bei Nokias Qt-Doku gibt es einen.Robokopp hat geschrieben: Wie muss ich diese Datentypen definieren?
Andere Frage: Wie wolltest Du denn bisher die einegegeben Gruppen speichern? Viele Anfänger nehmen eben ein QListWidget und stellen dann fest, dass sie manuell ein Mapping zwischen Item und dem dahinter liegenden Daten bauen müssen. Genau das leistet aber das Zusammenspiel von Model View und Controller letztlich einfacher und besser.
Naja, Du kannst es Dir doch mal im Designer angucken. Außerdem habe ich deswegen ja auch den Screenshot gemacht.Wiegesagt, ich hab noch keinen Bezug zu den UI Files und ich weiß nicht, wie sie arbeiten, weswegen ich damit nicht wirklich was anfangen kann
Mir ging es um das UI-Design im allgemeinen. Ich kapiere halt Deinen Ansatz nicht so wirklich bzw. empfinde ihn atypisch. Vielleicht liege ich auch komplett daneben und Dein Entwurf bietet Funtktionalität oder Ergonomie für einen speziellen Anwendungsfall, den ich nicht kenne. Aus dem Bauch heraus wollte ich Dir damit nur zeigen, wie man das Problem obsolet machen kann, indem man Container-Widgets benutzt und die Buttons entsprechend logisch anordnet.
Es gibt da natürlich viele Wege nach Rom

Zu den Layouts: Ja, die sind komplexer, daher verwenden viele ja auch einen Designer zum Anordnen und Managen der UI-Elemente. Andererseits bekommst Du nur so ein wirklich flexibles und anpassungsfähigs Endprodukt. Starre Layouts passen sich ja nicht gut den verschiedenen Auflösungen, Schruftgrößen usw. an.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
button.clicked.connect(widget.hide())?Naja, indem Du eben je nach Button-Druck ein show() bzw. hide() für das entsprechende Widgets aufrufst.
Zur Speicherung hab ich mir noch garkeine Gedanken gemacht.Ich wollte erstmal das Grundgerüst aufbauen, sehen dass der Menüwechsel klappt usw.
Um die einzelnen Funktionen kümmere ich mich später, zumal ich noch garnicht weiß, wie genau da was zusammenarbeiten muss.
Werde mir das mal anschauen
Ich erstelle mir grad selbst eine UI im Designer unter der Verwendung des QStackWidgets, in der Hoffnung dass dies in meinem Fall funktioniert.
Denn es macht ja im Prinzip nichts anderes, als verschiedene Seiten anzuzeigen, was mein Problem lösen könnte
Noch ne Frage zu den UI´s:
Ich erstelle ein Grundgerüst mit Buttons, die ich alle benenne und richtig platziere.
Muss ich dann im eigentlichen Code nur noch die connect-Zeile schreiben und Button.show() unter die jeweilige Klasse schreiben?
Und was ist, wenn ich ein vollwertiges Signal-Slot Konzept im Designer festgelegt habe? Dann muss ich ja eigentlich nur noch dafür sorgen, dass der Button und das zugehörige Element angezeigt werden, oder?
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
z.B.Robokopp hat geschrieben:button.clicked.connect(widget.hide())?Naja, indem Du eben je nach Button-Druck ein show() bzw. hide() für das entsprechende Widgets aufrufst.

Prinzipiell ja. Das show() ist iirc auch überflüssig, weiß ich jetzt nicht aus dem Kopf. Ist im Zweifel ja aber durch Ausprobieren sofort ersichtlich. Ich würde Dir dann noch dazu raten, das uic-Modul zum einbinden der ui-Files zu nutzen. (und nicht durch pyuic per Hand eine Python datei zu erstellen).Robokopp hat geschrieben: Noch ne Frage zu den UI´s:
Ich erstelle ein Grundgerüst mit Buttons, die ich alle benenne und richtig platziere.
Muss ich dann im eigentlichen Code nur noch die connect-Zeile schreiben und Button.show() unter die jeweilige Klasse schreiben?
Und was ist, wenn ich ein vollwertiges Signal-Slot Konzept im Designer festgelegt habe? Dann muss ich ja eigentlich nur noch dafür sorgen, dass der Button und das zugehörige Element angezeigt werden, oder?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
habs jetzt so versucht:
Resultat: AttributeError: 'function' object has no attribute 'hide'
Ich flipp aus
Ich dachte, man muss die UI files immer konvertieren.
Code: Alles auswählen
newgrp.clicked.connect(self.delgrp.hide())
Ich flipp aus
Gut zu wissenPrinzipiell ja. Das show() ist iirc auch überflüssig, weiß ich jetzt nicht aus dem Kopf. Ist im Zweifel ja aber durch Ausprobieren sofort ersichtlich. Ich würde Dir dann noch dazu raten, das uic-Modul zum einbinden der ui-Files zu nutzen. (und nicht durch pyuic per Hand eine Python datei zu erstellen).
Ich dachte, man muss die UI files immer konvertieren.
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Du darfst die Funktion ja auch nicht aufrufen!Robokopp hat geschrieben:habs jetzt so versucht:Resultat: AttributeError: 'function' object has no attribute 'hide'Code: Alles auswählen
newgrp.clicked.connect(self.delgrp.hide())
Ich flipp aus
Code: Alles auswählen
newgrp.clicked.connect(self.delgrp.hide)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
Okay
ging auch nich
ich versuch des jetzt mit dem UI File
es ist soweit fertig, nun versuch ich die Buttons zuzuordnen
Da hab ich so meine Probleme
wenn jetzt ein Button im Dsigner exit heißt, kann ich irgendwie per exit.clicked.connect(self.close) nichts bewirken
Was mache ich falsch?
ging auch nich
ich versuch des jetzt mit dem UI File
es ist soweit fertig, nun versuch ich die Buttons zuzuordnen
Da hab ich so meine Probleme
wenn jetzt ein Button im Dsigner exit heißt, kann ich irgendwie per exit.clicked.connect(self.close) nichts bewirken
Was mache ich falsch?
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Bei mir geht es - du hast also etwas falsch gemacht!Robokopp hat geschrieben:Okay
ging auch nich
K.A. ohne Quellcode geht da wenigRobokopp hat geschrieben: wenn jetzt ein Button im Dsigner exit heißt, kann ich irgendwie per exit.clicked.connect(self.close) nichts bewirken
Was mache ich falsch?

encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
@Robokopp: An was und wie hast Du den Namen `exit` denn vor dieser Zeile gebunden?
Ich habe so ein bisschen das Gefühl, dass GUI noch nicht Deine Baustelle ist -- dir fehlen noch Grundlagen in der Sprache selbst.
Ich habe so ein bisschen das Gefühl, dass GUI noch nicht Deine Baustelle ist -- dir fehlen noch Grundlagen in der Sprache selbst.
Ok
Also bei mir geht jetzt eigentlich alles, was ein separates Fenster öffnet.About, Help und Exit (was ich als eigene Methode definieren musste)
Das mit dem Aufruf von Newgrp, Delgrp usw kann ja garnicht mehr gehen weil ich das jetzt alles im StackedWidget drin hab^^
Wie änder ich da jetzt die angezeigte Seite?
mit gehts nicht
mit aufruf der Methode newgrp, welche das beinhaltet:
auch nicht
Also bei mir geht jetzt eigentlich alles, was ein separates Fenster öffnet.About, Help und Exit (was ich als eigene Methode definieren musste)
Das mit dem Aufruf von Newgrp, Delgrp usw kann ja garnicht mehr gehen weil ich das jetzt alles im StackedWidget drin hab^^
Wie änder ich da jetzt die angezeigte Seite?
mit
Code: Alles auswählen
self.ui.newgrp.connect.stackedWidget.setCurrentIndex(self, 2)
mit aufruf der Methode newgrp, welche das beinhaltet:
Code: Alles auswählen
self.stackedWidget.setCurrentIndex(self, 2)
auch nicht
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Also Doku lesen musst Du schon mal lernen:
http://doc.qt.nokia.com/4.7/qstackedwid ... rentWidget
Ist doch sehr einfach zu finden!
http://doc.qt.nokia.com/4.7/qstackedwid ... rentWidget
Ist doch sehr einfach zu finden!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
Ja hab ich doch
daher hab ich ja auch das setCurrentIndex
bekomme aber folgenden Fehler
QStackedWidget.setCurrentIndex(int): argument 1 has unexpected type 'MainWindow'
Edit:
Hab das self mal weggelassen
self.stackedWidget.setCurrentIndex(2)
Jetzt ist der Fehler weg aber der Index wird trotzdem nicht gewechselt
daher hab ich ja auch das setCurrentIndex
bekomme aber folgenden Fehler
QStackedWidget.setCurrentIndex(int): argument 1 has unexpected type 'MainWindow'
Edit:
Hab das self mal weggelassen
self.stackedWidget.setCurrentIndex(2)
Jetzt ist der Fehler weg aber der Index wird trotzdem nicht gewechselt
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Aber offensichtlich nicht verstanden:Robokopp hat geschrieben:Ja hab ich doch
Doku hat geschrieben: the currently shown widget can be retrieved using the currentWidget() function, and altered using the setCurrentWidget() function.
s.o.Robokopp hat geschrieben: daher hab ich ja auch das setCurrentIndex

Wie BlackJack schon schrieb, mangelt es Dir an Basiswissen und Erfahrung:Robokopp hat geschrieben: bekomme aber folgenden Fehler
QStackedWidget.setCurrentIndex(int): argument 1 has unexpected type 'MainWindow'
"unexpected type" und dazu der Typ sagt Dir doch, dass Dein Aufruf falsch ist, da Du einen Typen übergibst, der nicht erwartet wird. In diesem Falle übergibst Du ein MainWindow-Objekt, die Funktion erwartet aber einen Integer.
Solche Fehler kann man leicht selber finden.
Wie kommst Du überhaupt darauf, da ein self zu übergeben?Robokopp hat geschrieben: Hab das self mal weggelassen
self.stackedWidget.setCurrentIndex(2)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert