Fenster mit QHBoxLayout schließen

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

BlackJack hat geschrieben:@Sirius3: Wobei man sich dann natürlich fragt wie/womit `CloseQWidget()` verknüpft wird, und das *ein* Attribut für das Fenster für MDI-Fenster, von denen man ja durchaus mehr als eins erzeugen kann, nicht funktionieren wird. Die `CloseQWidget()`-Methode schliesst dann immer nur das zuletzt geöffnete.
Wie ich die Funktion 'CloseQWidget()' verknüpfen würde?

Nach meiner Überlegung würde ich (nachdem die Klasse 'MyForm aus dem Modul TestDialog importiert wurde) in der Datei MDIForm.py die Klasse MyForm in die Klasse MDIFormular hinzufügen und anschließend mittels 'connect()' eine Verbindung zum Button herstellen, so dass der Klick auf den Button die Funktion 'CloseQWidget()' aufgerufen wird. Aber da fällt mir gerade auf, dass selbst hierbei das Schließen des QWidget nicht ganz funktioniert, auch wenn als Sirius3s Anmerkung berücksichtigt habe.

Code: Alles auswählen

# -*- coding: utf-8 -*-

import sys  

from PyQt4.QtGui import QMainWindow, QApplication, QAction, QMenuBar, QToolBar, QIcon, QMdiArea, QScrollBar, QMdiSubWindow
from PyQt4.QtCore import SIGNAL, SLOT, Qt

from MDIForm_Menue import MainWindow_MenuBar
from MDIForm_ToolBar import ToolBar_Manage, ToolBar_Close
from  Info import Information
from TestDialog import MyForm

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


        self.mdiArea = QMdiArea()                                       # Widget QMdiArea hinzufügen
        self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) # Horizontalen Scrollbalken hinzufügen
        self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)   # Vertikalen Scrollbaken hinzufügen
        self.setCentralWidget(self.mdiArea)                             # Diesen Widget QMDiArea den kompletten Hauptfenster ausfüllen


        self.MDIChild = MyForm()
        [...]

        self.MDIChild.BClose.clicked.connect(self.CloseQWidget)

    def CloseQWidget(self):
        self.subwindow.close()

BlackJack

@Sophus: Ich meinte damit nicht irgendwie wild herumprobieren und mit einem riesigen GUI-Toolkit anfangen, sondern die Grundlagen und Zusammenhänge lernen und verstehen.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Nun hoffe ich, dass ich diesmal eine vermeintliche Lösung gefunden habe. Was habe ich getan? Ich bin von QMdiArea auf QWorkspace "umgestiegen" bzw. QWorkspace dem Widget QMdiArea vorgezogen. Im Gegensatz zu QmdiArea musste ich nicht jeden Scrollbar (Horizontal und Vertikal) einzeln hinzufügen. Bei QWorkspace setzt man die ScrollBars einfach auf True und fertig. Ansonsten habe ich dieses Widget genauso wie QMdiAre in die Klasse 'MDIFormular' hinzugefügt. Hier der Code:

MDIForm.py

Code: Alles auswählen

import sys  

from PyQt4.QtGui import QMainWindow, QApplication, QAction, QMenuBar, QToolBar, QIcon, QMdiArea, QScrollBar, QMdiSubWindow, QMessageBox, QWorkspace

from PyQt4.QtCore import SIGNAL, SLOT, Qt

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

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

    def CreateNewMovie(self, event):                   # Neues Fenster für Film hinzufügen öffnen
        Fenster = MyForm(self)
        if  self.existUnterfenster(self.Dict_Language.Dict_TestDialog["Title"]): 
            reply = QMessageBox.question(self, (self.Dict_Language.Dict_Message_WindowExists["MessageTitle"]),
            self.Dict_Language.Dict_Message_WindowExists["MessageText"], QMessageBox.Ok)
            print "MessageBox wurde ausgegeben."
        else:
            self.workspace.addWindow(Fenster)
            Fenster.show()
            print "Dialog lädt"

    def existUnterfenster(self, Title):
       for window in self.workspace.windowList():
            if Title == window.windowTitle():
                return True
            print "Fenster bereits geladen"
TestDialog.py

Code: Alles auswählen

# -*- coding: utf-8 -*-
import sys
from PyQt4.QtGui import QWidget, QApplication, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QPushButton, QMessageBox, QTextEdit, QMdiSubWindow, QDialog, QMdiArea
from PyQt4.QtCore import Qt

class MyForm(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        self.setAttribute(Qt.WA_DeleteOnClose)
        #Layout festlegen
        self.setLayout(QVBoxLayout())
        #Eingabe Widget mit Text erstellen
        pHBox = QHBoxLayout()
        self.LLabel = QLabel(self.Chosen_Language.Dict_TestDialog["Label1"])
        self.LEMsg = QLineEdit()
        #Ins Layout packen und Layout ins Widget packen
        pHBox.addWidget(self.LLabel)
        pHBox.addWidget(self.LEMsg)
        self.layout().addLayout(pHBox)

        #2 Buttons hinzufuegen
        pHBox = QHBoxLayout()
        self.BShow = QPushButton(self.Chosen_Language.Dict_TestDialog["cmd_Ok"])
        self.BClose = QPushButton(self.Chosen_Language.Dict_TestDialog["cmd_Beenden"])
        #Ins Layout packen
        pHBox.addWidget(self.BShow)
        pHBox.addWidget(self.BClose)
        self.layout().addLayout(pHBox)

       #Zeigen−Button bei Klick showMessage aufrufen lassen, Signal und Slot
       #verbinden
        self.BShow.clicked.connect(self.showMessage)
       #Beim Klick auf Beenden−Button schliessen, Signal und Slot verbinden
        self.BClose.clicked.connect(self.CloseMe)

    def CloseMe(self):
        print "Fenster wird geschlossen.."
        self.close()

# In einer MesssageBox nochmal nachfragen, ob das Programm wirklich geschlossen
# werden soll.
    def closeEvent(self, event):
        reply = QMessageBox.question(self, (self.Chosen_Language.Dict_Message["MessageTitle"]),
            self.Chosen_Language.Dict_Message["MessageText"], QMessageBox.Yes, QMessageBox.No)

        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()


if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    myapp = MyForm()
    myapp.show()
    sys.exit(app.exec_())
Also, das Fenster wird wunderbar geschlossen. Für diejenigen, die es gerne mal probieren wollen, stelle ich mein kleines Projekt gerne online zum Herunterladen zur Verfügung: Herunterladen.


Wenn ihr noch Kritik oder Anmerkungen habt, dann immer her damit. Aber ich habe noch eine Frage an euch. Augenscheinlich konnte ich keinen Unterschied zwischen den beiden Widgets QWorkspace und QMdiArea feststellen - abgesehen von den Namen. Ist QWorkspace "älter" als QMdiArea? Und wie man im Modul "TestDialog.py" sehr deutlich sehen kann, war es mir möglich durch einfache 'close()'-Methode das Fenster zu schließen. QMdiArea scheint da wesentlich mächtiger zu sein, und gibt sich wohl nicht einfach so mit 'close()' zufrieden.
BlackJack

@Sophus: Der Mensch der keine Dokumentation lesen mag ist wieder da. Ich denke ja immer noch das ist alles nicht ernst gemeint und Du trollst hier gegen Wochendende einfach aus langeweile rum. :-)

Ziemlich am Anfang in der Qt-Doku zu `QWorkspace`:
This class is obsolete. It is provided to keep old source code working. We strongly advise against using it in new code.
Die Hervorhebung ist *nicht* von mir, die steht so in der Doku.

Und bei den Details dann als zweites der Satz „This class is deprecated. Use QMdiArea instead.”
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

BlackJack hat geschrieben:@Sophus: Der Mensch der keine Dokumentation lesen mag ist wieder da. Ich denke ja immer noch das ist alles nicht ernst gemeint und Du trollst hier gegen Wochendende einfach aus langeweile rum. :-)

Ziemlich am Anfang in der Qt-Doku zu `QWorkspace`:
This class is obsolete. It is provided to keep old source code working. We strongly advise against using it in new code.
Die Hervorhebung ist *nicht* von mir, die steht so in der Doku.

Und bei den Details dann als zweites der Satz „This class is deprecated. Use QMdiArea instead.”
Ich kann dir versichern, dass ich keineswegs trollen mag. Aus dem Alter sollte ich als angehender Lehrer und als bald 32 jähriger Mann doch sein. Gut, die Klasse ist also veraltet. Ist es jetzt nun veraltet, weil es jetzt den QMdiArea gibt oder welche gravierende Lücken hat nun QWorkspace? Da freut man sich einen zweiten Ast, dass man als blutiger Anfänger es hinbekommen hat, dass das QWidget sich endlich schließt. Ohne Scherz, ich habe schon fast Jubelsprünge gemacht :-) Und Sirius3s Beispiel, mit dem Schließen des QWidgets innerhalb des Widgets QMdiArea hat auch nicht gefruchtet. Also irgendwie scheint QMdiArea ziemlich bissig zu sein oder QMdiArea kann mich nicht leiden.
BlackJack

@Sophus: Wenn die Entwickler einer Bibliothek *dringend* davon abraten eine Klasse für neuen Code zu verwenden, dann verwendet man die einfach nicht mehr. Insbesondere dann nicht wenn eine Alternative zur Verfügung gestellt wird, die man stattdessen verwenden kann.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

BlackJack hat geschrieben:@Sophus: Wenn die Entwickler einer Bibliothek *dringend* davon abraten eine Klasse für neuen Code zu verwenden, dann verwendet man die einfach nicht mehr. Insbesondere dann nicht wenn eine Alternative zur Verfügung gestellt wird, die man stattdessen verwenden kann.
Du scheinst das was die Entwickler von sich sagen einfach so hinzunehmen wie ein Soldat. Guter Soldat. Es mag ja durchaus eine Berechtigung vorliegen, weswegen die Entwickler uns eindringlich davon abraten, aber ich hätte gern eine Erklärung, weshalb die Entwickler uns davon abraten. So bleibt am Ende des Tages die Entscheidung immer noch bei mir, ob ich nun QWorkspace oder QMdiArea benutze oder nicht, und nicht bei den Entwicklern. Die Entwickler können einem viel erzählen, wenn der Tag lang ist. Daher hätte ich gerne gewusst, was so gravierend schlecht an QWorkspace sein soll - mal davon abgesehen, dass die Entwickler uns dringend davon abraten. Und die Alternative erweist sich aber (zumindest aus meinen Augen) nicht gerade als benutzerfreundlich im Umgang mit dem Schließen von QWidgets. Dagegen ist QWorkspace recht freundlich.
BlackJack

@Sophus: Nein, nicht wie ein Soldat, sondern wie ein vernünftiger Programmierer der davon ausgeht das es schon einen guten Grund dafür geben wird wenn die Entwickler einer Bibliothek eine Komponente in Rente schicken und eine Alternative anbieten. Ich hinterfrage halt nicht alles so zwanghaft nervig wie Du. Nicht ohne Grund. Und da ich mit dem `QMdiArea` nach lesen der Dokumentation weder Probleme habe die Scrollbalken zu aktivieren, noch ein Widget für ein Subfenster zu implementieren dem ich eine `close()`-Methode verpasst habe, die sich das dazugehörige `QMdiSubWindow`-Exemplar in dem es selbst dargestellt wird, auf eine sehr einfache und offensichtliche Weise besorgt, sehe ich auch gar keinen Grund die Frage nach dem warum zu stellen. Wenn sich die Entwickler die Mühe machen einen Ersatz zu programmieren *wird es einen Grund geben*. Einen der wichtig genug war um sich die Arbeit zu machen.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@Sophus: Die Info, warum die Klasse zurückgezogen wurde, findest Du im Netz. Es ist Dein Interesse, also recherchiere danach. Falls die Antworten zu kryptisch oder unbefriedigend sind, empfehle ich eine gründliche Einarbeitung in C++ und die Konzepte von Qt.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Nun, ich bin mit QMdiArea nicht ganz zufrieden. Das Schließen des Fensters löse ich sehr unelegant. Wie man im Code sehen kann, muss ich das Widget Pushbutton (Bclose) aus dem Modul "TestDialog" aus der Klasse "MyForm" hier in die Klasse "MDIFormular" hinzufügen. Selbst als blutiger Anfänger darf man sicherlich seine temporäre Meinung bilden. Und meiner Meinung nach ist das Arbeiten mit QWorkspace wesentlich einfacher. Da muss ich nicht erst den Pushbutton aus "TestDialog.py" in die Klasse "MDIFormular" hinzufügen. Ich kann gleich mit dem PushButton "Bclose" dort im "TestDialog" arbeiten, indem ich einfach die 'close()'-Methode anwende. Entweder stelle ich mich mal wieder sehr "trollig" an (um BlackJack Glauben zu schenken, dass ich den lieben langen Tag nichts besseres zu tun habe, als zu trollen) oder aber QMdiArea schlägt hier einen Umweg ein.

MDIForm.py

Code: Alles auswählen

import sys
from PyQt4.QtGui import QMainWindow, QApplication, QAction, QMenuBar, QToolBar, QIcon, QMdiArea, QScrollBar, \
    QMdiSubWindow, QMessageBox, QWorkspace, QScrollArea

from PyQt4.QtCore import Qt
from Xarphus.TestDialog import MyForm

class MDIFormular(QMainWindow):
    # Vererbung aktivieren, angeben, dass es keine Elternform hat
    def __init__ (self, parent=None): 
        QMainWindow.__init__(self, parent)
        [...]
        self.MDIFenster = MyForm()

        self.mdiArea = QMdiArea()                                       # Widget QMdiArea hinzufügen
        self.mdiArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) # Horizontalen Scrollbalken hinzufügen
        self.mdiArea.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)   # Vertikalen Scrollbaken hinzufügen
        self.setCentralWidget(self.mdiArea)

        self.MDIFenster.BClose.clicked.connect(self.CloseQWidget) # Widget "PushButton" aus dem Modul "TestDialog.py" wird in die Klasse "MDIFormular" hinzugefügt.      
        [...]
   def CreateNewMovie(self):
# Vorher durch die Funktion "existUnterfenster" prüfen ob das Fenster bereits geöffnet wurde
# Wenn Ja, dann MessageBox ausgeben...
        if  self.existUnterfenster(self.Dict_Language.Dict_TestDialog["Title"]): # Titel wird aus der Sprachdatei importiert
            reply = QMessageBox.critical(self, (self.Dict_Language.Dict_Message_WindowExists["MessageTitle"]),
            self.Dict_Language.Dict_Message_WindowExists["MessageText"])
            print "MessageBox wurde ausgegeben."
        else:
# Nein, Unterfenster gibt es noch nicht, also öffne...
            self.subwindow = self.mdiArea.addSubWindow(self.MDIFenster)
            self.MDIFenster.setAttribute(Qt.WA_DeleteOnClose)
            self.MDIFenster.show()
            print "Dialog lädt"

    def existUnterfenster(self, Title):
        for window in self.mdiArea.subWindowList():
            if Title == window.windowTitle():
                return True
            print "Fenster bereits geladen"

# Widget Pushbutton "Bclose" ist mit dieser Funktion verknüpft.
    def CloseQWidget(self):
        self.subwindow.close()
        print "Dialog wurde soeben erfolgreich geschlossen."

if __name__ == "__main__":
    print 'Dieses Programm läuft als Main.'
else:
    print 'Das Programm wird von einem anderen Modul importiert.'
        #MDIFormular
app = QApplication(sys.argv)
app.setAttribute(Qt.AA_DontShowIconsInMenus, False)
MDIWindow = MDIFormular()
MDIWindow.showMaximized()
sys.exit(app.exec_())
TestDialog.py

Code: Alles auswählen

# -*- coding: utf-8 -*-
import sys
from PyQt4.QtGui import QWidget, QApplication, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QPushButton, \
QMessageBox, QTextEdit, QMdiSubWindow, QDialog, QMdiArea

from PyQt4.QtCore import Qt

from Xarphus.Config import SetConfig
# QMdiSubWindow
class MyForm(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        self.setAttribute(Qt.WA_DeleteOnClose)
        [...]
        # 1 Button hinzufuegen
        pHBox = QHBoxLayout()
        self.BClose = QPushButton(self.Chosen_Language.Dict_TestDialog["cmd_Beenden"])
        #Ins Layout packen
        pHBox.addWidget(self.BClose)
        self.layout().addLayout(pHBox)

       #Beim Klick auf Beenden−Button schliessen, Signal und Slot verbinden
        #self.BClose.clicked.connect(self.CloseMe)
        
#    def CloseMe(self):
#        print "Funktion angenommen."
        #self.setWindowTitle("Blah")
        #self.mdiArea = QMdiArea()
        #self.mdiArea.closeAllSubWindows()
        #self.mdiArea.removeSubWindow(self)
        #self.mdiArea.closeActiveSubWindow()
        #self.subwindow.close()
        #self.close()
         [...]
if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    myapp = MyForm()
    myapp.show()
    sys.exit(app.exec_())
BlackJack

@Sophus: Die Lösung ist in der Tat nicht gut. Man kann aber *sehr einfach* in einer Methode auf dem Widget welches in einem Subwindow angezeigt wird, an dieses Subwindow-Objekt heran kommen um darauf dann die `close()`-Methode aufzurufen. Dazu muss man das Objektmodell von Qt und den Objektbaum und die „Besitzer”-Beziehung zwischen Objekten zur Laufzeit verstanden haben. Das steht in der Qt-Dokumentation.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

BlackJack hat geschrieben:@Sophus: Die Lösung ist in der Tat nicht gut. Man kann aber *sehr einfach* in einer Methode auf dem Widget welches in einem Subwindow angezeigt wird, an dieses Subwindow-Objekt heran kommen um darauf dann die `close()`-Methode aufzurufen. Dazu muss man das Objektmodell von Qt und den Objektbaum und die „Besitzer”-Beziehung zwischen Objekten zur Laufzeit verstanden haben. Das steht in der Qt-Dokumentation.
Gibt es Tutorials, die sich mit diesem Schwerpunkt beschäftigen? Wenn ja, hättest du da welche parat?
BlackJack

@Sophus: Ob es welche gibt weiss ich nicht, was auch gleich die zweite Frage beantwortet. Die Qt-Dokumentation `QObject` und was von dort zum Thema verlinkt ist würde mir allerdings reichen. Dazu kann man sich noch eine kleine rekursive Funktion schreiben die einen Objektbaum als Text ausgibt, um zu sehen ob man das verstanden hat, und wenn Du diese Funktion dann auf das oberste Widget in Deiner Anwendung anwendest, dann siehst Du die Beziehung zwischen Deinem Widget und dem `QMdiArea`-Objekt.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

BlackJack hat geschrieben:@Sophus: Ob es welche gibt weiss ich nicht, was auch gleich die zweite Frage beantwortet. Die Qt-Dokumentation `QObject` und was von dort zum Thema verlinkt ist würde mir allerdings reichen. Dazu kann man sich noch eine kleine rekursive Funktion schreiben die einen Objektbaum als Text ausgibt, um zu sehen ob man das verstanden hat, und wenn Du diese Funktion dann auf das oberste Widget in Deiner Anwendung anwendest, dann siehst Du die Beziehung zwischen Deinem Widget und dem `QMdiArea`-Objekt.
Na los, hau auf mich drauf. Ich habe mich soeben mit dem Thema 'QObject' auseinandergesetzt. Soweit ich es verstanden habe, werden die Klassen vom QObject abgeleitet. In meinem Fall wären es MyForm und MDIFormular. In dem gezeigten Pseudo-Code befinden sich beide Klassen in einem Modul. In meinem Fall habe ich je eine Klasse ein Modul. Wo ich allerdings eine Frage habe, ist, wenn ich mir diesen Pseudo-Code anschaue, sehe ich keinen geringen Unterschied zu meinem Beispiel, bzw. weniger eleganten Lösung. Denn auch hier wird das Modul "Widget" in die Klasse "Application" hinzugefügt. Und dann werden zu den Funktionen eine Verknüpfung hergestellt. Mir will nicht ganz ersichtlich sein, was jetzt hier der große Unterschied zu meiner Lösung sein soll? Hier ein Pseudo-Code:

Code: Alles auswählen


class Widget(QObject):

    def noArgument(self):
        self.emit(PYSIGNAL("sigNoArgument"), ())

    def oneArgument(self):
        self.emit(PYSIGNAL("sigOneArgument"), (1, ))

    def twoArguments(self):
        self.emit(PYSIGNAL("sigTwoArguments"), (1, "two"))

class Application(QObject):

    def __init__(self):
        QObject.__init__(self)

        self.widget = Widget()

        self.connect(self.widget, PYSIGNAL("sigNoArgument"),
                        self.printNothing)
        self.connect(self.widget, PYSIGNAL("sigOneArgument"),
                        self.printOneArgument)
        self.connect(self.widget, PYSIGNAL("sigTwoArguments"),
                        self.printTwoArguments)
        self.connect(self.widget, PYSIGNAL("sigTwoArguments"),
                        self.printVariableNumberOfArguments)

    def printNothing(self):
        print "No arguments"

    def printOneArgument(self, arg):
        print "One argument", arg

    def printTwoArguments(self, arg1, arg2):
        print "Two arguments", arg1, arg2

    def printVariableNumberOfArguments(self, *args):
        print "list of arguments", args
BlackJack

@Sophus: Ich weiss jetzt ehrlich gesagt nicht was das nun mit, äh, irgendwas zu tun haben soll. Also zumindest sehe ich keine Verbindung zum Problem. Aber ich sehe das Dir Grundbegriffe fehlen, nicht nur bei Qt sondern ganz allgemein bei Python. Der Satz „Denn auch hier wird das Modul "Widget" in die Klasse "Application" hinzugefügt.” ergibt hinten und vorne keinen Sinn. Es gibt in dem gezeigten Quelltext kein `Widget`-Modul und der Klasse `Application` werden nur Methoden per ``def``-Anweisungen hinzugefügt.

Auf den Objektbaum der von Qt-Objekten aufgespannt wird bist Du überhaupt nicht eingegangen.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

BlackJack hat geschrieben:@Sophus: Ich weiss jetzt ehrlich gesagt nicht was das nun mit, äh, irgendwas zu tun haben soll. Also zumindest sehe ich keine Verbindung zum Problem. Aber ich sehe das Dir Grundbegriffe fehlen, nicht nur bei Qt sondern ganz allgemein bei Python. Der Satz „Denn auch hier wird das Modul "Widget" in die Klasse "Application" hinzugefügt.” ergibt hinten und vorne keinen Sinn. Es gibt in dem gezeigten Quelltext kein `Widget`-Modul und der Klasse `Application` werden nur Methoden per ``def``-Anweisungen hinzugefügt.
Me culpa. Entschuldige. Du hast Recht, es gibt gar kein Modul. Ich hatte gedanklich den Beispielcode und mein Projekt vollkommen durcheinander geworfen. Widget ist im gezeigten Code eine Klasse. Und was ich mit dem gezeigten Code aufzeigen wollte? Nun, ich habe mich im Internet recherchiert und zwar nach dem Stichwort 'QObject' und bin dann unter anderem darauf gestoßen. Hier. Aber wieder mal lag ich komplett daneben. Wäre ja auch zu schön um wahr zu sein :-)
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

BlackJack hat geschrieben:@Sophus: Ich weiss jetzt ehrlich gesagt nicht was das nun mit, äh, irgendwas zu tun haben soll. Also zumindest sehe ich keine Verbindung zum Problem. Aber ich sehe das Dir Grundbegriffe fehlen, nicht nur bei Qt sondern ganz allgemein bei Python. Der Satz „Denn auch hier wird das Modul "Widget" in die Klasse "Application" hinzugefügt.” ergibt hinten und vorne keinen Sinn. Es gibt in dem gezeigten Quelltext kein `Widget`-Modul und der Klasse `Application` werden nur Methoden per ``def``-Anweisungen hinzugefügt.

Auf den Objektbaum der von Qt-Objekten aufgespannt wird bist Du überhaupt nicht eingegangen.
Übrigens, eine Frage habe ich, bevor ich mir mühselig in Google nach "QObject Objecktbaum Python" suche, wollte ich gerne wissen, was an meiner Variante denn "verehrt" sei? Für mich ist es eher deshalb unelegant, weil ich über Umwege den Widget PushButton (Bclose) mit der Funktion CloseQWidget in der Klasse "MDIFormular" im Modul "TestDialog.py" herstelle. Abgesehen von diesem "Umweg" hätte ich gerne gewusst, inwieweit es nicht gut sein soll? Ist es nur eine Geschmackfrage? Oder verbirgt sich dahinter eher eine organisatorische Frage?
BlackJack

@Sophus: Das `MDIFormular`-Objekt muss dafür zu viel von den Fenstern wissen die darin dargestellt werden. Dass das Objekt eine Schaltfläche zum Schliessen besitzt und das dieses Attribut `BClose` heisst, sollte das `MDIFormular`-Objekt nicht wissen müssen. Und dann funktioniert das *so* ja gerade mal mit *einem* Fenster. So einen MDI-Bereich benutzt man ja weil man mehrere Fenster haben möchte. Und zwar normalerweise auch vom selben Typ. Weshalb ich diese Einschränkung auf ein Fenster nicht so ganz verstehe. Zumal der Umweg über den Fenstertitel umständlich ist. Und eine Testmethode die entweder `True` oder `None` statt `True` oder `False` zurück gibt hat eine unschöne API.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

BlackJack hat geschrieben:@Sophus: Das `MDIFormular`-Objekt muss dafür zu viel von den Fenstern wissen die darin dargestellt werden. Dass das Objekt eine Schaltfläche zum Schliessen besitzt und das dieses Attribut `BClose` heisst, sollte das `MDIFormular`-Objekt nicht wissen müssen. Und dann funktioniert das *so* ja gerade mal mit *einem* Fenster. So einen MDI-Bereich benutzt man ja weil man mehrere Fenster haben möchte. Und zwar normalerweise auch vom selben Typ. Weshalb ich diese Einschränkung auf ein Fenster nicht so ganz verstehe. Zumal der Umweg über den Fenstertitel umständlich ist. Und eine Testmethode die entweder `True` oder `None` statt `True` oder `False` zurück gibt hat eine unschöne API.
BlackJack: In meinem Projekt arbeite ich erstmal mit einem SubWindow. Erst wenn ich alles richtig gemacht habe, darunter zählt auch das Schließen vom SubWindow, dann erweitere ich das Ganze. Aber allgemein will ich, dass für jede Kategorie ein Fenster aufmachbar ist. Spielen wir mal ein Szenario durch. Du weißt ja mittlerweile, dass ich mit meinem Projekt eher auf Datenbank-Anwendung hinaus will. Nun, unter Filmen gibt es zwei Kategorien, einmal Filme und einmal Serien. Wenn ich also nun eine Serie hinzufügen möchte, und im MenuItem auf "Serie hinzufügen" geklickt habe, wieso sollte der Benutzer die Möglichkeit haben nochmal ein neues Fenster in der Kategorie "Serie" öffnen zu können? Sollte der Anwender nicht erstmal eine Serie hinzufügen bevor er eine nächste hinzufügen will? Daher sehe ich es sinnlos, wenn man eine Serie hinzufügen will, aber gleich 4 Fenster offen hat. Wozu? Ich kann eh nur eine Serie hinzufügen - ein nach dem anderen. In einer MDI-Anwendung kann ich aber mehrere Fenster aus unterschiedlichen Bereichen haben.

Nun zu der Geschichte mit QObject und Objektbaum. Ich habe heute den ganzen Tag damit zugebraucht und Google ständig missbraucht, um irgendwas darüber zu finden. Irgendwie bin ich da nicht weit gekommen. Man findet nichts konkretes zu dem, worauf du am Ende hinaus wolltest. Ich fand weder Tutorials noch Beispiele noch gute Erklärungen.
BlackJack

@Sophus: Die Frage ist IMHO eher warum man dem Benutzer nicht erlauben sollte mehrere Fenster zum Hinzufügen von Filmen anzuzeigen. Wenn er das nicht möchte, muss er es ja nicht tun. Was ist durch das Verbot gewonnen, das man sich durch zusätzlichen Code erkaufen muss?
Antworten