Menue Triggered

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

Hallo,

Ich war nun dabei eine Menueleiste zu erstellen. Vorher hatte ich den Code in einer Datei, und nun wollte ich sehen, wie es mit dem Auslagern funktioniert. Das Auslagern klappt, die Menueleiste wird im MainWindow ordnungsgemäß angezeigt. Schauen wir mal in die Datei MDIFom.py. Mir geht es dabei besonders darum, ein triggered auszulösen. Allgemein klappt er auch, nur klappt er bei jedem Menupunkt, wo ich mich doch nur auf den Menupunkt "Beenden" konzentriere. Den Menupunkt "Beenden" habe ich der Klasse "MDIFormular" hinzugefügt (Zeile 37). In Zeile 39 wird "mnuMainWindowClose" als Parameter mittel der Methode "SetMenuBar" übergeben. Damit kennt die Klasse "MDIFormular" nun "mnuMainWindowClose". In Zeile 42 setze ich den "triggered" und übergebe im Parameter den Namen der Funktion "MnuCloseMain". Und in den Zeilen 44-66 habe ich dann die eben genannte Funktion definiert. Er soll beim Klick auf "mnuMainWindowClose" eine print-Anweisung ausgeben und das Programm anschließend beenden.

ABER, wie ihr in der Date Menue.py seht, habe ich mehrere Menupunkte (Filme, Bücher, Notizen etc...) und das Problem ist, die Funktion gibt sie an alle Menupunkte weiter, wo ich doch nur "Beenden" haben wollte. Bei allen Menupunkten wird das Programm beendet.

Was habe ich also übersehen?

MDIForm.py

Code: Alles auswählen

# -*- coding: cp1252 -*-
#import os
import sys  # Wie alle Module muss auch das Modul sys mittels der import-Anweisung eingebunden werden,
            # also import sys. Das sys-Modul stellt Informationen in Konstanten, Funktionen und
            # Methoden über den Python-Interpreter zur Verfügung.
# Hier greift man auf bestimmte Elemente der grafischen Benutzeroberfläche zu, und nicht auf ALLE Elemente
from PyQt4.QtGui import QMainWindow, QApplication, QAction, QMenuBar
# HIer werden nur SIGNAL und SLOT aufgerufen.
from PyQt4.QtCore import SIGNAL, SLOT
from Menue import MenueLeiste

# Die Fensterklasse "MDIFormular" wird von QMainWindow abgeleitet, einer Klasse, die schon die
# wichtigsten Elemente eines Hauptfensters mitbringt.
class MDIFormular(QMainWindow):
    # Vererbung aktivieren, angeben, dass es keine Elternform hat
    def __init__ (self, parent=None): 
        QMainWindow.__init__(self, parent)
        # Die MainWindow-Form bekommt hier einen Titel.
        self.setWindowTitle(' Xarphus Build 0.1')
        # Hier wird ein bestimmter Text über die Statusbar ausgegeben.
        self.statusBar().showMessage('Ready')

        self.MNUL_Verwaltung = MenueLeiste() # Hier wird der Klasse "MDIFormular" eine 
                                                                       # Instanz der Klasse "MenueLeiste" aus der Datei
                                                                       # MenueLeiste.py hinzufuegt.
        self.setMenuBar(self.MNUL_Verwaltung)# Anschließend wird durch die Methode "setMenuBar" der 
                                                                       # Klasse "MDIFormular" 
                                                                       # die Instanz self.mnuMenueleiste übergeben.
                                                                       # Hier muss  self.MNUL_Verwaltung als Parameter übergeben werden 
                                                                       # --> also self.setMenuBar(self.MNUL_Verwaltung)
        
        self.MNUL_Info = MenueLeiste()
        self.setMenuBar(self.MNUL_Info)

        # Hier wir die Klasse "MenueLeiste" der Klasse "MDIFormular"
        # hinzugefuegt. 
        self.mnuMainWindowClose = MenueLeiste()
        # Hier wird durch die die Methode "setMenuBar" der Parameter übergeben.
        self.setMenuBar(self.mnuMainWindowClose)

        # Durch "MnuCloseMain" soll der Trigger mit der Funktion  "MnuCloseMain" verdrahtet werden
        self.mnuMainWindowClose.triggered.connect(self.MnuCloseMain) 
    
    def MnuCloseMain(self): # Eine Funktion definiert
        print "Ihr Programm wurde soeben erfolgreich beendet."
        self.close()
     
# Main Routine
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)
MDIWindow = MDIFormular()

MDIWindow.showMaximized()
# Startet die Anwendung und wartet, bis das Fenster geschlossen 
sys.exit(app.exec_())
Menue.py

Hier habe ich eine Klasse für meinen Menu erstellt. Viele hätten gern eine Funktion daraus gemacht. Aber ich denke, es ist eher eine philosophische Frage.

Code: Alles auswählen

# -*- coding: cp1252 -*-
import sys  # Wie alle Module muss auch das Modul sys mittels der import-Anweisung eingebunden werden,
                  # also import sys. Das sys-Modul stellt Informationen in Konstanten, Funktionen und
                  # Methoden über den Python-Interpreter zur Verfügung.

from PyQt4.QtGui import QAction, QMenuBar
from PyQt4.QtCore import SIGNAL, SLOT

class MenueLeiste(QMenuBar):
    def __init__ (self, parent=None):
        QMenuBar.__init__(self, parent)

########################################################
########### Menupunkte gehören zum Menu "Verwaltung" ###############
 ########################################################
        # Menupunkt bekommt eine Beschriftung, hier 'Film'
        mnuFilm = QAction ('Filme', self)
        # Hier wird zu der Beschrifung hinzugefügt, über welche Tastenkombinationen
        # man zum Film kommt.
        mnuFilm.setShortcut('Ctrl+F')
        # Sobald man mit der Maus über das Untermenu fährt, erscheint in der Statusbar
        # der Text, hier 'Filme hinzufügen'.
        mnuFilm.setStatusTip('Filme hinzufügen')

        mnuBuch = QAction ('Bücher', self)
        # Hier wird zu der Beschrifung hinzugefügt, über welche Tastenkombinationen
        # man zum Film kommt.
        mnuBuch.setShortcut('Ctrl+F')
        # Sobald man mit der Maus über das Untermenu fährt, erscheint in der Statusbar
        # der Text, hier 'Filme hinzufügen'.
        mnuBuch.setStatusTip('Bücher hinzufügen')

        mnuMusik = QAction ('Musik', self)
        # Hier wird zu der Beschrifung hinzugefügt, über welche Tastenkombinationen
        # man zum Film kommt.
        mnuMusik.setShortcut('Ctrl+F')
        # Sobald man mit der Maus über das Untermenu fährt, erscheint in der Statusbar
        # der Text, hier 'Filme hinzufügen'.
        mnuMusik.setStatusTip('Musik hinzufügen')

        mnuAdressbuch = QAction ('Kontakte', self)
        # Hier wird zu der Beschrifung hinzugefügt, über welche Tastenkombinationen
        # man zum Film kommt.
        mnuAdressbuch.setShortcut('Ctrl+F')
        # Sobald man mit der Maus über das Untermenu fährt, erscheint in der Statusbar
        # der Text, hier 'Filme hinzufügen'.
        mnuAdressbuch.setStatusTip('Kontaktdaten hinzufügen')

        mnuNotizen = QAction ('Notizen', self)
        # Hier wird zu der Beschrifung hinzugefügt, über welche Tastenkombinationen
        # man zum Film kommt.
        mnuNotizen.setShortcut('Ctrl+F')
        # Sobald man mit der Maus über das Untermenu fährt, erscheint in der Statusbar
        # der Text, hier 'Filme hinzufügen'.
        mnuNotizen.setStatusTip('Notizen hinzufügen')

        
        mnuTrennstrich = QAction ('-', self) # Hier will der Trennstrich nicht funktionieren

        # Menupunkt bekommt eine Beschriftung, hier 'Beenden'
        mnuMainWindowClose = QAction ('Beenden', self)
        # Hier wird zu der Beschrifung hinzugefügt, über welche Tastenkombinationen
        # man dwn MainWindow beenden kann.
        mnuMainWindowClose.setShortcut('Ctrl+Q')
        # Sobald man mit der Maus über das Untermenu fährt, erscheint in der Statusbar
        # der Text, hier 'Programm beenden'.
        mnuMainWindowClose.setStatusTip('Programm beenden')
        # Klickt man auf auf das Untermenu "MainWindowClose" wird ein bestimmtes Ereignis
        # ausgelöst, hier wird der MainWindow geschlossen.
        #self.connect(mnuMainWindowClose, SIGNAL('triggered()'), SLOT('close()'))
        #self.mnuMainWindowClose.triggered.connect(close)
        
###############################################################
###### Menupunkte gehören zum Menu "Info" ################################
###############################################################

        # Menupukt bekommt eine Beschriftung, hier 'Info'
        mnuUeber = QAction ('Über Xarphus', self)
        # Hier wird zu der Beschrifung hinzugefügt, über welche Tastenkombinationen
        # man zum Film kommt.
        mnuUeber.setShortcut('Ctrl+F')
        # Sobald man mit der Maus über das Untermenu fährt, erscheint in der Statusbar
        # der Text, hier 'Filme hinzufügen'.
        #mnuUeber.setStatusTip('Alles über Xarphus')
        # Statusbar wird erstellt.
        #self.statusBar()

###################################################
###### Menuleiste "Verwaltung" #############################
###################################################

        # Eine eigenständige Menubar wird erstellt. In diesem Fall nur einer, und zwar mit der
        # Beschriftung "Verwaltung"
	#menubar = QMenuBar()
        MNUL_Verwaltung = self.addMenu('&Verwaltung')
        # Zum Menü "Verwaltung" werden weitere Menüpunkte erstellt.
        # MNUL steht hier für MenuLeiste
        # MNUP steht hier für MenuPunkt
        MNUL_Verwaltung.addAction(mnuFilm)
        MNUL_Verwaltung.addAction(mnuBuch)
        MNUL_Verwaltung.addAction(mnuMusik)
        MNUL_Verwaltung.addAction(mnuAdressbuch)
        MNUL_Verwaltung.addAction(mnuNotizen)
        MNUL_Verwaltung.addAction(mnuTrennstrich)
        MNUL_Verwaltung.addAction(mnuMainWindowClose)

#############################
###### Menuleiste "Info" ###########
#############################

        # Eine eigenständige Menubar wird erstellt. In diesem Fall nur einer, und zwar mit der
        # Beschriftung "Info"
        # MNUL steht hier für MenuLeiste
        # MNUP steht hier für MenuPunkt
        #menubar = self.menuBar()
        MNUL_Info = self.addMenu('&?')
        # Zum Menü "Verwaltung" werden weitere Menüpunkte erstellt.
        MNUL_Info.addAction(mnuUeber)
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

Warum erzeugst Du drei mal die MenueLeiste? Und dann versuch mal herauszufinden, wann der Trigger, den Du in Zeile 42 mit MnuCloseMain verknüpfst, ausgelöst wird, das heißt, an was Du ihn alles bindest.

PS: falls Du jemand motivieren willst, deine Beiträge zu lesen, versuch den Code so kurz wie möglich zu halten. Insbesondere unnötige Kommentare löschen, auskommentierte Zeilen löschen, alles was nicht dazu beiträgt, den Fehler zu finden, löschen.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Hallo Sirius3, in welcher Zeile erzeuge ich drei Mal die Menuleiste?
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

Zeile 23, 32 und 37.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Ich habe mal die Zeilen auskopiert (Ich hoffe, ich habe sie richtig kopiert):

Code: Alles auswählen

        self.MNUL_Verwaltung = MenueLeiste()
       
        self.MNUL_Info = MenueLeiste()

        self.mnuMainWindowClose = MenueLeiste()
Nach meinem Verständnis wird hier wird der Klasse "MDIFormular" eine Instanz der Klasse "MenueLeiste" aus der Datei MenueLeiste.py hinzufuegt. Ich ging davon aus, dass ich sie jedesmal einzeln der Klasse hinzufügen müsste. Mein Fehler. Ich habe MNUL_Info und "mnuMainWindowClose" auskommentiert und es klappt. Danke für den Hinweis. Jetzt muss ich mich noch um den Triggered kümmern.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

MDIForm.py

Code: Alles auswählen

# -*- coding: cp1252 -*-
import sys
from PyQt4.QtGui import QMainWindow, QApplication, QAction, QMenuBar

from PyQt4.QtCore import SIGNAL, SLOT
from Menue import MenueLeiste

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

        self.setWindowTitle(' Xarphus Build 0.1')

        self.statusBar().showMessage('Ready')
        
        self.MNUL_Verwaltung = MenueLeiste()                                     
        self.setMenuBar(self.MNUL_Verwaltung)
        
        self.DoShowClose.triggered.connect(self.MnuCloseMain) 
        
    def MnuCloseMain(self): 
        print "Ihr Programm wurde soeben erfolgreich beendet."
        self.setWindowTitle("Blah") 

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)
MDIWindow = MDIFormular()

MDIWindow.showMaximized()
sys.exit(app.exec_())
Ich habe nun in der Menu.py-Datei ein wenig aufgeräumt und den Code etwas umgeschrieben, damit es für mich übersichtlicher wird. Hier in diesem Beispiel werden zwei Menupunke ausgegeben, und zwar Filme und Beenden.

Menu.py

Code: Alles auswählen

# -*- coding: cp1252 -*-
import sys  

from PyQt4.QtGui import QAction, QMenuBar
from PyQt4.QtCore import SIGNAL, SLOT

class MenueLeiste(QMenuBar):
    def __init__ (self, parent=None):
        QMenuBar.__init__(self, parent)

        ##########################################################################
        ###### Menuleiste "Verwaltung" ###########################################
        ##########################################################################
        # Eine eigenständige Menubar wird erstellt. In diesem Fall nur einer, und zwar mit der
        # Beschriftung "Verwaltung"
	    #MNUL_Verwaltung = QMenuBar()
        MNUL_Verwaltung = self.addMenu('&Verwaltung')
        
        DoShowFilm = QAction("Filme", self)
        DoShowFilm.setShortcut("Ctrl+F")
        DoShowFilm.setStatusTip("Filme hinzufügen")
        MNUL_Verwaltung.addAction(DoShowFilm)
        
        DoShowClose = QAction("Beenden", self)
        DoShowClose.setShortcut("Ctrl+Q")
        DoShowClose.setStatusTip("Programm beenden")
        MNUL_Verwaltung.addAction(DoShowClose)    
Leider will es mir noch nicht ganz gelingen. Ich bekomme die Fehlermeldung:
Traceback (most recent call last):
File "D:\Dan\Python\Start.py", line 3, in <module>
from Xarphus.MDIForm import MDIFormular
File "D:\Dan\Python\Xarphus\MDIForm.py", line 63, in <module>
MDIWindow = MDIFormular()
File "D:\Dan\Python\Xarphus\MDIForm.py", line 35, in __init__
self.setMenuBar(self.DoShowClose)
AttributeError: 'MDIFormular' object has no attribute 'DoShowClose'
Nach meinem Verständnis habe ich in Zeilen 16 und 17 der Klasse "MDIFormular" die Klasse "MenueLeiste" hinzugefügt. Dadurch - so verstehe ich das - sollte "DoShowClose" doch bekannt sein - schließlich wurde sie in der "Menue.py-Datei dem Menu zugewiesen. Was und welche Zeile übersehe ich hier einfach?
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

Warum sollte, wenn die Menü-Instanz ein Attribut DoShowClose hat, plötzlich MdiFormular auch eines haben, nur weil das Attribut MNUL_Verwaltung eine Menü-Instanz ist?
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Sirius3 hat geschrieben:Warum sollte, wenn die Menü-Instanz ein Attribut DoShowClose hat, plötzlich MdiFormular auch eines haben, nur weil das Attribut MNUL_Verwaltung eine Menü-Instanz ist?
Wir reden hier über diese Zeile, richtig?

Code: Alles auswählen

        self.DoShowClose.triggered.connect(self.MnuCloseMain)
Ich gehe mal diese Zeile Wort für Wort durch:

MDIFormular.InDerMenüleisteDoShowClose.DasTriggeredEvent.SollVerknüpftWerdenMit(MDIFormular.MethodeMnuCloseMain)

Damit möchte ich am Ende, dass der Menuounkt "DoShowClose" die Funktion ausführen soll.

Code: Alles auswählen

    def MnuCloseMain(self):
        print "Ihr Programm wurde soeben erfolgreich beendet."
        self.setWindowTitle("Blah")
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

Was Du Dir wünschst, und was da wirklich steht sind zwei verschiedene Dinge.
Attribute tauchen nicht aus dem Nichts auf. Solange Du Deinem MDIFormular kein DoShowClose-Attribut gibts, hat es auch keines.
Benutzeravatar
Sophus
User
Beiträge: 1109
Registriert: Freitag 25. April 2014, 12:46
Wohnort: Osnabrück

Aus dem"geheimnisvollen" Wort "Attribut", welches für mich so gewaltig klingt, ging am Ende ein winziges Wörtchen "self" hervor. Schlussendlich habe ich sowohl in der Menu.py-Datei und MDIForm.py-Datei einige kleine Veränderungen vorgenommen. Ich setze überall dort ein self.

MDIForm.py

Code: Alles auswählen

import sys
from PyQt4.QtGui import QMainWindow, QApplication, QAction, QMenuBar

from PyQt4.QtCore import SIGNAL, SLOT
from Menue import MenueLeiste

class MDIFormular(QMainWindow):

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

        self.setWindowTitle(' Xarphus Build 0.1')

        self.statusBar().showMessage('Ready')
        
        self.MNUL_Verwaltung = MenueLeiste() 
        self.setMenuBar(self.MNUL_Verwaltung)

       # Hier nahm ich eine Veränderung vor
        self.MNUL_Verwaltung.DoShowClose.triggered.connect(self.MnuCloseMain) 
        
    def MnuCloseMain(self): 
        print "Ihr Programm wurde soeben erfolgreich beendet."
        self.setWindowTitle("Blah") 

if __name__ == "__main__":
    print 'Dieses Programm läuft als Main.'
else:
    print 'Das Programm wird von einem anderen Modul importiert.'
app = QApplication(sys.argv)
MDIWindow = MDIFormular()

MDIWindow.showMaximized()
sys.exit(app.exec_())
Menu.py

Code: Alles auswählen

import sys  

from PyQt4.QtGui import QAction, QMenuBar

class MenueLeiste(QMenuBar):
    def __init__ (self, parent=None):
        QMenuBar.__init__(self, parent)
       # Hier sitzt überall ein self (Attribute)
        self.MNUL_Verwaltung = self.addMenu('&Verwaltung')
        
        self.DoShowFilm = QAction("Filme", self)
        self.DoShowFilm.setShortcut("Ctrl+F")
        self.DoShowFilm.setStatusTip("Filme hinzufügen")
        self.MNUL_Verwaltung.addAction(self.DoShowFilm)
        
        self.DoShowClose = QAction("Beenden", self)
        self.DoShowClose.setShortcut("Ctrl+Q")
        self.DoShowClose.setStatusTip("Programm beenden")
        self.MNUL_Verwaltung.addAction(self.DoShowClose)
Antworten