Seite 1 von 2
Widget ausblenden/beenden
Verfasst: Sonntag 13. Februar 2011, 18:24
von Robokopp
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)
Re: Widget ausblenden/beenden
Verfasst: Sonntag 13. Februar 2011, 18:31
von lunar
Was verstehst Du denn unter „ins andere Widget wechseln“?
Re: Widget ausblenden/beenden
Verfasst: Sonntag 13. Februar 2011, 18:34
von Hyperion
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:
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
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:
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]
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?
Re: Widget ausblenden/beenden
Verfasst: Sonntag 13. Februar 2011, 18:40
von Robokopp
Hier mal der Code:
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_())
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
Re: Widget ausblenden/beenden
Verfasst: Sonntag 13. Februar 2011, 19:15
von BlackJack
@Robokopp: Vergiss am besten erst einmal, dass es `setGeometry()` gibt. Widgets werden mit Layouts platziert.
Re: Widget ausblenden/beenden
Verfasst: Sonntag 13. Februar 2011, 19:18
von Robokopp
Aber so ist es irgendwie einfacher^^
Da kann ich alles so anordnen wie ich will
Aber zu meinem eigentlichen Problem:
Wie krieg ich diese Buttons wieder weg?
mit einem simplen del ist es nicht getan irgendwie
Re: Widget ausblenden/beenden
Verfasst: Sonntag 13. Februar 2011, 19:20
von Hyperion
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.
Re: Widget ausblenden/beenden
Verfasst: Sonntag 13. Februar 2011, 19:30
von Robokopp
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
Re: Widget ausblenden/beenden
Verfasst: Sonntag 13. Februar 2011, 19:52
von Hyperion
Robokopp hat geschrieben:Ich versteh grad garnix mehr
Ich vermute einfach mal, das liegt daran, dass es hier ziemlich viele XY-Probleme gibt
Robokopp hat geschrieben:
Der WindowTitel wird aber angezeigt.
Stimmt, mein Fehler.
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.
Naja, indem Du eben je nach Button-Druck ein show() bzw. hide() für das entsprechende Widgets aufrufst.
Robokopp hat geschrieben:
Wie muss ich diese Datentypen definieren?
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.
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.
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
Naja, Du kannst es Dir doch mal im Designer angucken. Außerdem habe ich deswegen ja auch den Screenshot gemacht.
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.
Re: Widget ausblenden/beenden
Verfasst: Sonntag 13. Februar 2011, 20:00
von Robokopp
Naja, indem Du eben je nach Button-Druck ein show() bzw. hide() für das entsprechende Widgets aufrufst.
button.clicked.connect(widget.hide())?
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?
Re: Widget ausblenden/beenden
Verfasst: Sonntag 13. Februar 2011, 20:06
von Hyperion
Robokopp hat geschrieben:Naja, indem Du eben je nach Button-Druck ein show() bzw. hide() für das entsprechende Widgets aufrufst.
button.clicked.connect(widget.hide())?
z.B.
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?
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).
Re: Widget ausblenden/beenden
Verfasst: Sonntag 13. Februar 2011, 20:13
von Robokopp
habs jetzt so versucht:
Resultat: AttributeError: 'function' object has no attribute 'hide'
Ich flipp aus
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).
Gut zu wissen
Ich dachte, man muss die UI files immer konvertieren.
Re: Widget ausblenden/beenden
Verfasst: Sonntag 13. Februar 2011, 20:58
von Hyperion
Robokopp hat geschrieben:habs jetzt so versucht:
Resultat: AttributeError: 'function' object has no attribute 'hide'
Ich flipp aus
Du darfst die Funktion ja auch nicht aufrufen!
Re: Widget ausblenden/beenden
Verfasst: Sonntag 13. Februar 2011, 21:29
von Robokopp
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?
Re: Widget ausblenden/beenden
Verfasst: Sonntag 13. Februar 2011, 21:31
von Hyperion
Robokopp hat geschrieben:Okay
ging auch nich
Bei mir geht es - du hast also etwas falsch gemacht!
Robokopp 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?
K.A. ohne Quellcode geht da wenig

Ich würde mal drauf tippen, dass Du "self.exit" nehmen musst. Aber das hängt natürlich durchaus von der Art ab, wie Du die UI-Daten in Deinen Code einbaust.
Re: Widget ausblenden/beenden
Verfasst: Sonntag 13. Februar 2011, 21:33
von BlackJack
@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.
Re: Widget ausblenden/beenden
Verfasst: Sonntag 13. Februar 2011, 21:51
von Robokopp
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
Code: Alles auswählen
self.ui.newgrp.connect.stackedWidget.setCurrentIndex(self, 2)
gehts nicht
mit aufruf der Methode newgrp, welche das beinhaltet:
auch nicht
Re: Widget ausblenden/beenden
Verfasst: Sonntag 13. Februar 2011, 21:54
von Hyperion
Also Doku lesen musst Du schon mal lernen:
http://doc.qt.nokia.com/4.7/qstackedwid ... rentWidget
Ist doch sehr einfach zu finden!
Re: Widget ausblenden/beenden
Verfasst: Sonntag 13. Februar 2011, 22:08
von Robokopp
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
Re: Widget ausblenden/beenden
Verfasst: Sonntag 13. Februar 2011, 22:27
von Hyperion
Robokopp hat geschrieben:Ja hab ich doch
Aber offensichtlich nicht verstanden:
Doku hat geschrieben:
the currently shown widget can be retrieved using the currentWidget() function, and altered using the setCurrentWidget() function.
Robokopp hat geschrieben:
daher hab ich ja auch das setCurrentIndex
s.o.
Robokopp hat geschrieben:
bekomme aber folgenden Fehler
QStackedWidget.setCurrentIndex(int): argument 1 has unexpected type 'MainWindow'
Wie BlackJack schon schrieb, mangelt es Dir an Basiswissen und Erfahrung:
"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.
Robokopp hat geschrieben:
Hab das self mal weggelassen
self.stackedWidget.setCurrentIndex(2)
Wie kommst Du überhaupt darauf, da ein self zu übergeben?