Öffne zweite Form auch als Unterfenster (MDI)

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Ich weiß schon, warum ich das Widget QWorkspace eher mag als MDiArea. Denn letzteres ist verdammt umständlich. Ich stelle beide Versionen gegenüber, einmal QWorkspace und QMdiArea. In beiden Versionen geht es um das Öffnen und Schließen eines Unterfensters.

Arbeiten mit QMdiArea:

Code: Alles auswählen


# Die Importe dienen nur zu Testzwecken. Mir ist klar, dass man nur das
# importieren soll, was man auch tatsächlich braucht
 
from PyQt4.QtGui import *
from PyQt4.QtCore import *

class Mdi_Main(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)

        self.mdiArea = QMdiArea()
        self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
        self.setCentralWidget(self.mdiArea)

        self.actionTestWindow.triggered.connect(self.createMdiChild)

    def createMdiChild(self):
        self.check_window = Check_Window(self)
        self.check_window.setAttribute(Qt.WA_DeleteOnClose)
        self.check_window.pushButtonCancel.clicked.connect(self.close_it)

        self.subwindow = QMdiSubWindow()
        self.subwindow.setWidget(self.check_window)
        self.mdiArea.addSubWindow(self.subwindow)

        self.check_window.show()
        self.subwindow.show()
        self.subwindow.widget().show()

    def close_it(self):
        self.mdiArea.removeSubWindow(self.subwindow)
Also, wenn ich mir allein für das Öffnen eines Fensters betrachte, dann muss ich mit dem Kopf schütteln. Auf diesem "Rattenschwanz" bin ich gekommen, weil in der Qt-Dokumentation folgendes steht:
Removes widget from the MDI area. The widget must be either a QMdiSubWindow or a widget that is the internal widget of a subwindow. Note widget is never actually deleted by QMdiArea. If a QMdiSubWindow is passed in its parent is set to 0 and it is removed, but if an internal widget is passed in the child widget is set to 0 but the QMdiSubWindow is not removed.
Das heißt, ich brauche eine QMdiSubWindow -Klasse, damit ich am Ende das Fenster auch schließen kann.

Jetzt schaue ich mir mal QWorkspace an:
Arbeiten mit QWorkspace :

Code: Alles auswählen


# Die Importe dienen nur zu Testzwecken. Mir ist klar, dass man nur das
# importieren soll, was man auch tatsächlich braucht
 
from PyQt4.QtGui import *
from PyQt4.QtCore import *

class Mdi_Main(QMainWindow):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)

        self.workspace = QWorkspace()
        self.workspace.setScrollBarsEnabled(True)
        self.setCentralWidget(self.workspace)

        self.actionTestWindow.triggered.connect(self.createMdiChild)

    def createMdiChild(self):
        self.check_window = Check_Window(self)
        self.check_window.setAttribute(Qt.WA_DeleteOnClose)
        self.check_window.pushButtonCancel.clicked.connect(self.close_it)

        self.workspace.addWindow(self.check_window)
        self.check_window.show()

    def close_it(self):
        self.check_window.close()
Mein persönliches Fazit:
Wenn ich mir die beiden Möglichkeiten anschaue, einmal das Arbeiten mit MdiArea und dann mit QWorkspace, dann fällt doch deutlich auf, dass im QWorkspace erheblich weniger Code nötig ist, allein für das Öffnen des Unterfenster. Mal davon abgesehen, dass auf in Qt-Dokumentation ausdrücklich behauptet wird, dass diese Klasse angeblich veraltet sei, frage ich mich, wieso ich auf MdiArea umsteigen sollte, wenn es doch so umständlich ist? Dagegen ist das Arbeiten mit QWorkspace wesentlich angenehmer. Oder aber ich habe im Code was gewaltig falsch gemacht. Ich will ja auch keine Grundsatz Diskussion starten, aber ich sitze hier und rolle mit den Augen und frage mich, wieso das so umständlich sein muss? Und allgemein, welchen Nachteil hätte ich, wenn ich QWorkspace weiterhin benutze? Ich meine, die Klasse funktioniert ja bisher anstandslos. Mal abgesehen davon, dass mit dem Objektbaum innerhalb des QWorkspace-Widgets. Vielleicht mag mir da wer mehr Licht ins Dunkle bringen, außer mit der Aussage "Aber ind er Qt-Dokumentation steht doch, dass ist veraltet....". Lesen kann ich ja selbst :-)
BlackJack

@Sophus: Diese Diskussion fängst Du jetzt im Forum zum dritten mal an. :roll:

Benutz doch `QWorkspace`, ignoriere das man das nicht mehr benutzen soll, freu Dich das Du kein guter Soldat bist der alles ungefragt hinnimmt (hast Du mir in einer der letzten Diskussionen über das Thema vorgeworfen), sondern ein individueller Freigeist der gerne gegen den Strom schwimmt. Ganz tolle Idee beim Programmieren…

Oder ich versuch mal wieder meine Vermutung das Du trollst. Denn das ist wohl die umständlichste Art in der man das MDI-Fenster erstellen kann und es enthält auch offensichtlich redundanten Code. Ich würde auch weder den Abbruch-Button an dieser Stelle verbinden, noch `close_it()` überhaupt implementieren. Und auch das alles nicht an `self` binden denn das funktioniert ja ganz offensichtlich so nicht korrekt wenn man mehr als ein MDI-Fenster erstellt. Das hier sollte alles sein was man braucht:

Code: Alles auswählen

    def createMdiChild(self):
        self.mdiArea.addSubWindow(CheckWindow(), Qt.WA_DeleteOnClose)
Wahnsinnig kompliziert…
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@BlackJack: So einfach ist es eben nicht. Versuch mal über die Schließ-Schaltfläche das Unterfenster zu schließen. Nur die Widgets auf der Form verschinden. Erst durch meinen "umständlichen" Code bin ich in der Lage das Fenster zu schließen. Ich weiß, dass viele von euch auf einem Unterfenster keine Schaltfläche sehen wollt, die das Fenster schließt. Und nein, ich trolle nicht. Keine Ahnung wie du auf diese Vermutung kommst. Ich habe eher gehofft, dass man mich mehr aufklären könnte, als die bloße Tatsache, dass das QWorkspace veraltet sei. Und wenn mein Code so drollig aussieht, liegt es daran, das ich kein Profi bin, sondern ein richtiger, blutiger Anfänger.
BlackJack

@Sophus: Kleine Korrektur:

Code: Alles auswählen

    def new_child_window(self):
        self.mdi_area.addSubWindow(ChildWindow()).show()
(Das `Qt.WA_DeleteOnClose` setze ich in der `ChildWindow.__init__()`). Wenn nur die Widgets innerhalb des MDI-Fensters verschwinden, dann hast Du wohl auch nur das innere Widget geschlossen und nicht das Fenster. *Das* hat jetzt aber nicht wirklich etwas damit zu tun wie man das Kindfenster erzeugt, sondern was die Schaltfläche an Aktionen auslöst.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@BlackJack: Du meinst, die removeSubWindow-Methode ist die falsche Wahl? Also in diesem Kontext? Mit der bloßen close()-Methode komme ich ebenso nicht weiter.
BlackJack

@Sophus: Man muss halt `close()` auf dem richtigen Objekt aufrufen. Das Thema hatten wir aber schon mal. Du musst Dir klar machen welche Objekte es dort gibt, wie der Objektbaum aussieht, und wie man den navigiert.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@BlackJack: Nur aus reine Neugier. Was hat mein Weg für einen Nachteil. Du hast ja gesehen, dass ich über Umstände mit der QMdiSubWindow-Klasse gearbeitet habe. Mal davon abgesehen, dass es umständlich ist, hätte ich gerne gewusst, worin in meinem Weg die Grenze liegen. Oder kann man unter Umständen meinen Weg auch als "Alternative" betrachten? So nach dem Motto "Es führen viele Wege nach Rom".
BlackJack

@Sophus: Ich hatte ja schon geschrieben dass das so nicht funktioniert sobald man mehr als ein Fenster öffnet. Und ein MDI-Bereich mit nur einem Fenster macht nicht viel Sinn.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@Sophus:
Du kannst es halten wie ein Dachdecker. Viele Wege führen nach Rom, fast nichts ist alternativlos. Hoffnungslos dagegen ist weitaus häufiger.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@BlackJack: Zu diesem Thema fand ich diese Seite:

https://qt.gitorious.org/pyside/pyside- ... y#LNaN-NaN

Ich werde sie mal genauer anschauen müssen.
BlackJack

@Sophus: Das ist das Beispiel aus der Qt-Dokumentation in Python umgesetzt. Da kommt Dein Problem nicht drin vor. Du willst ja unbedingt eine Schaltfläche *in* dem MDI-Fenster zum Schliessen haben. Das Beispiel verwendet den üblichen Weg die MDI-Fenster über das entsprechende Icon in der Fensterleiste zu schliessen oder das aktive MDI-Fenster über ein Menü/eine Aktion.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

@BlackJack: Wenn du MDI-Fenster sagst, dann meinst du sicherlich das Unterfenster, also das Kind-Fenster, richtig? Und ja, ich will da unbedingt eine Schaltfläche drin haben. :-) So ungewöhnlich ist es ja nicht, dass man eine Schaltfläche zum Schließen direkt auf dem Unterfenster haben will :-) Und das Beispiel beschreibt zwar nicht mein Problem, jedoch hat es weitere interessante Ansätze.
Antworten