Hallo, ich hab da mal ne wahrscheinlich banale Frage:
ich möchte dynamisch Splitter in einander schachteln, also Splitter in Splitter USW.
Jedoch sollen die Splitter wieder dynamisch "unsplitted" werden, also durch den user z.b.
Statisch ist mir das klar (addwidet qsplitter).
Es gibt jedoch kein delwidget oder was ähnliches (jedenfalls habe ich nix gefunden)
Wie kann man das denn in pyqt lösen ?
Danke im Vorraussetzung für jeden Tip.
Qsplitter in qpsplitter
So ganz versteh ich nicht was Du am End willst aber evt. hilft es ja das Widget einfach zu verstecken ?
Wenn ein Widget irgendwo aus einem anderen Grund zerstört wird sollte sich Qt um das entfernen aus dem Splitter kümmern.
Vielleicht hilfts !?
Falls nicht erklär mal wie der User die Widgets und Splitter dynamisch verwalten soll
Gruß
Code: Alles auswählen
widget.hide()
#oder die equivalente Funktion (Slot):
setVisible(false)
#weiter wären da noch
widget.close()
# was da geht lies bitte in der Doku
Vielleicht hilfts !?
Falls nicht erklär mal wie der User die Widgets und Splitter dynamisch verwalten soll
Gruß
- py_fan_berlin
- User
- Beiträge: 13
- Registriert: Dienstag 7. September 2010, 21:00
Danke für den Tipp,
hide funktioniert (falls das widget noch benötigt wird) und
destroy ebenfalls (wenn nicht).
Ich hab mir das viel zu kompliziert gemacht, einfach den betroffene splitter
Destroyen, pyqt löscht alle Child Widgets und dann ggf. einen neuen Splitter
Mit addwidget hinzufügen.
Zu deiner Frage, wozu das Ganze:
Im linken Frame sollen unterschiedliche Objekte aufgelistet werden und
je nach Objekt-Typ werden im rechten Frame andere Inhalte ggf. In mehreren
Frames (Splitter) angezeigt.
Der Benutzer kann also links unterschiedliche Objekte anklicken und
erhält rechts je nach Objekt-Typ eine andere Bildschirmaufteilung.
Somit muss die Aufteilung für das zuvor angeklickte Objekt vorher gelöscht werden.
Nochmals danke für deine Antwort.
hide funktioniert (falls das widget noch benötigt wird) und
destroy ebenfalls (wenn nicht).
Ich hab mir das viel zu kompliziert gemacht, einfach den betroffene splitter
Destroyen, pyqt löscht alle Child Widgets und dann ggf. einen neuen Splitter
Mit addwidget hinzufügen.
Zu deiner Frage, wozu das Ganze:
Im linken Frame sollen unterschiedliche Objekte aufgelistet werden und
je nach Objekt-Typ werden im rechten Frame andere Inhalte ggf. In mehreren
Frames (Splitter) angezeigt.
Der Benutzer kann also links unterschiedliche Objekte anklicken und
erhält rechts je nach Objekt-Typ eine andere Bildschirmaufteilung.
Somit muss die Aufteilung für das zuvor angeklickte Objekt vorher gelöscht werden.
Nochmals danke für deine Antwort.
"QWidget.destroy()" ist nicht dafür gedacht, von außen aufgerufen zu werden. Diese Methode löscht das Steuerelemente und seine Kinder sofort, was schief gehen kann, wenn das Steuerelement noch benutzt wird (e.g. durch das Fenstersystem). Verwende "QWidget.deleteLater()", um Steuerelemente permanent zu löschen.
- py_fan_berlin
- User
- Beiträge: 13
- Registriert: Dienstag 7. September 2010, 21:00
Lunar, danke für deine Anmerkung.
- py_fan_berlin
- User
- Beiträge: 13
- Registriert: Dienstag 7. September 2010, 21:00
Also ich dachte ja ich wäre mit dem Problem durch, aber das klappt alles trotzdem nicht.
Ich habe hier mal einen Beispielcode zusammengestellt:
Wenn wie im Code test = False ist, dann erscheint ein Window mit einem Splitter in der Mitte und links und recht je ein Frame
und jeweils eine halbe Windowseite breit. So weit so gut.
Wenn ihr test = True setzt, wird der rechte Frame gelöscht und ein 2-ter Splitter mit zwei Frames in den ersten Splitter eingesetzt.
Jedoch nimmt nun der erste Frame aus dem ersten Splitter fast das gesamte Window ein.
Er soll jedoch nur die Hälfte einnehmen und die rechte Hälfte durch den 2. Splitter aufteilen lassen.
Ich dachte erst es liegt am löschen des 2. Frames (jedoch scheint es daran nicht zu liegen)
ich habe es auf alle erdenklichen Arten (deleteLater bis zu sip.delete) versucht jedoch bleibt das Resultat das Gleiche.
Auch das setzen den Stretchfactors nach einsetzen des 2.Splitter wirkt nicht.
Was kann ich noch machen, ich bin mit meinem Latein am Ende ...
Danke für jede Anregung.
Ich habe hier mal einen Beispielcode zusammengestellt:
Code: Alles auswählen
import sip
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Standard_Window(QMainWindow):
def __init__ (self, parent):
super(Standard_Window, self).__init__(parent)
self.setMinimumSize(400,300)
self.resize(800,600)
self.setWindowTitle("Windowtitel")
self.statusBar().showMessage("Statuszeile")
self.setAutoFillBackground(True)
return
def Standard_Frame(self,frame):
frame.setFrameStyle(QFrame.StyledPanel)
frame.setBackgroundRole(QPalette.Light)
frame.setAutoFillBackground(True)
return frame
if __name__ == '__main__':
app = QApplication(sys.argv)
window = Standard_Window(None)
splitter = QSplitter(Qt.Horizontal)
frame1 = QFrame()
frame1 = window.Standard_Frame(frame1)
frame2 = QFrame()
frame2 = window.Standard_Frame(frame2)
splitter.addWidget(frame1)
splitter.addWidget(frame2)
splitter.setStretchFactor(0, 1)
splitter.setStretchFactor(1, 1)
window.setCentralWidget(splitter)
test = False
if test == True:
splitter2 = QSplitter(Qt.Vertical)
frame21 = QFrame()
frame21 = window.Standard_Frame(frame21)
frame22 = QFrame()
frame22 = window.Standard_Frame(frame22)
splitter2.addWidget(frame21)
splitter2.addWidget(frame22)
splitter2.setStretchFactor(0, 1)
splitter2.setStretchFactor(1, 1)
# "alten" Frame aus Splitter löschen
frame2.hide()
frame2.deleteLater()
print("Anzahl nach delete/destroy: ",splitter.count())
sip.delete(frame2)
print("Anzahl nach sip.delete: ",splitter.count())
# 2.Splitter in 1.Splitter einsetzen
splitter.addWidget(splitter2)
print("Anzahl nach add(Splitter2): ",splitter.count())
splitter.setStretchFactor(0, 1)
splitter.setStretchFactor(1, 1)
window.show()
app.exec_()
und jeweils eine halbe Windowseite breit. So weit so gut.
Wenn ihr test = True setzt, wird der rechte Frame gelöscht und ein 2-ter Splitter mit zwei Frames in den ersten Splitter eingesetzt.
Jedoch nimmt nun der erste Frame aus dem ersten Splitter fast das gesamte Window ein.
Er soll jedoch nur die Hälfte einnehmen und die rechte Hälfte durch den 2. Splitter aufteilen lassen.
Ich dachte erst es liegt am löschen des 2. Frames (jedoch scheint es daran nicht zu liegen)
ich habe es auf alle erdenklichen Arten (deleteLater bis zu sip.delete) versucht jedoch bleibt das Resultat das Gleiche.
Auch das setzen den Stretchfactors nach einsetzen des 2.Splitter wirkt nicht.
Was kann ich noch machen, ich bin mit meinem Latein am Ende ...
Danke für jede Anregung.
ich glaube du suchst einen Fehler, den es gar nicht gibt. Solange du keinen Inhalt in den Frames hast, spielt es doch keine Rolle wie das Layout aussieht. Wenn du zum Beispiel statt ein Frame ein QLabel einsetzt wird der rechte Teil grösser.
Die ganzen stretch Funktionen kannst du auch weglassen.
Deinen Konstruktor (oder wie der in Python auch immer heisst) von Standard_Window schreibt man üblicherweise so:
also das None als default Wert. Dann kannst du auf das None beim erstellen des Standard_Window verzichten.
Code: Alles auswählen
splitter2.addWidget(QLabel(" ".join([str(i) for i in range(40)])))
splitter2.addWidget(frame22)
Deinen Konstruktor (oder wie der in Python auch immer heisst) von Standard_Window schreibt man üblicherweise so:
Code: Alles auswählen
def __init__ (self, parent = None):
super(Standard_Window, self).__init__(parent)
- py_fan_berlin
- User
- Beiträge: 13
- Registriert: Dienstag 7. September 2010, 21:00
Hallo DaMutz, danke für deine Antwort.
Ich möchte das Label nicht direkt in den Splitter setzen, sondern z.B. in den Frame22.
Habe ich gemacht, sieht auch so aus wie ich mit das vorstelle.
Aber jetzt muss ich den Splitter von Hand in die Mitte setzen um das Label sehen zu können.
Genau das soll automatisch geschehen und nicht der Benutzer machen müssen.
Ich möchte das Label nicht direkt in den Splitter setzen, sondern z.B. in den Frame22.
Habe ich gemacht, sieht auch so aus wie ich mit das vorstelle.
Aber jetzt muss ich den Splitter von Hand in die Mitte setzen um das Label sehen zu können.
Genau das soll automatisch geschehen und nicht der Benutzer machen müssen.
die Standard_Frame Methode sollte man wohl eher nicht in diese Klasse integrieren. Die Funktion hat mit der Klasse gar nichts zu tun. Ich habe die QFrame Klasse erweitert, ist meiner Meinung nach um einiges besser.
Ich weiss nicht ob meine Lösung, so ist wie du es erwartest. Vielleicht weiss jemand anderes eine elegantere Lösung:
Ich weiss nicht ob meine Lösung, so ist wie du es erwartest. Vielleicht weiss jemand anderes eine elegantere Lösung:
Code: Alles auswählen
#~ coding: utf-8
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class StandardWindow(QMainWindow):
def __init__ (self, parent = None):
super(StandardWindow, self).__init__(parent)
self.setMinimumSize(400,300)
self.resize(800,600)
self.setWindowTitle("Windowtitel")
self.statusBar().showMessage("Statuszeile")
self.setAutoFillBackground(True)
class StandardFrame(QFrame):
def __init__(self, parent = None):
super(StandardFrame, self).__init__(parent)
self.setFrameStyle(QFrame.StyledPanel)
self.setBackgroundRole(QPalette.Light)
self.setAutoFillBackground(True)
def main():
app = QApplication(sys.argv)
window = StandardWindow()
splitter = QSplitter(Qt.Horizontal)
splitter.setChildrenCollapsible(False)
frame1 = StandardFrame()
frame2 = StandardFrame()
splitter.addWidget(frame1)
splitter.addWidget(frame2)
window.setCentralWidget(splitter)
test = True
if test == True:
layout = QVBoxLayout()
for label_text in ['hallo', 'python-forum']:
label = QLabel(label_text)
layout.addWidget(label)
splitter2 = QSplitter(Qt.Vertical)
frame21 = StandardFrame()
frame22 = StandardFrame()
frame22.setLayout(layout)
splitter2.addWidget(frame21)
splitter2.addWidget(frame22)
# "alten" Frame aus Splitter löschen
frame2.deleteLater()
# 2.Splitter in 1.Splitter einsetzen
splitter.addWidget(splitter2)
window.show()
app.exec_()
if __name__ == '__main__':
main()
- py_fan_berlin
- User
- Beiträge: 13
- Registriert: Dienstag 7. September 2010, 21:00
Hallo DaMutz,
klar die Standard_Frame Methode als Erweiterung der QFrame Klasse ist natürlich genau richtig so.
Die Verwendung von QVBoxLayout im frame22 bringt den richtigen Effekt, den Frameinhalt anzuzeigen.
Wenn ich jetzt noch frame1 auf 1/4 der Windowbreite fixieren kann (unabhängig von der rechten Hälfte)
dann bin ich super zu frieden.
klar die Standard_Frame Methode als Erweiterung der QFrame Klasse ist natürlich genau richtig so.
Die Verwendung von QVBoxLayout im frame22 bringt den richtigen Effekt, den Frameinhalt anzuzeigen.
Wenn ich jetzt noch frame1 auf 1/4 der Windowbreite fixieren kann (unabhängig von der rechten Hälfte)
dann bin ich super zu frieden.
Code: Alles auswählen
splitter.moveSplitter(50, 1)
- py_fan_berlin
- User
- Beiträge: 13
- Registriert: Dienstag 7. September 2010, 21:00
Klappt super, if test = True (nach addWidget(splitter2).
Geht aber nicht, if test = False ???
Geht aber nicht, if test = False ???