SystemTrayIcon nimmt Kontextmenü nicht an

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
Shaldy
User
Beiträge: 123
Registriert: Sonntag 2. März 2008, 22:49

Hey Leute!

Ich habe eine vom SystemTrayIcon abgeleitete Klasse, die ein Kontextmenü bereit stellen und ein(en?) ToolTip anzeigen soll.

Code: Alles auswählen

from PyQt4.QtGui import *

class SystemTray(QSystemTrayIcon):

    def __init__(self, app, parent = None):
        QSystemTrayIcon.__init__(self, parent)
        self.app = app

        self.setIcon(
            QIcon( r"C:\Python25\CreateNic Test\GUI\Res\icon-taskleiste.png" )
            )

        menu = QMenu()
        menu.addAction("Einstellungen")
        menu.addAction("Bugbericht senden")
        menu.addAction("Hilfe")
        menu.addSeparator()
        menu.addAction("Beenden")
        
        self.setContextMenu(menu)
        self.setToolTip("CreateNic DesktopPanel (Version 1.0)")
        self.contextMenu().triggered.connect(self.triggered)

    def triggered(self, action):
        if action.text() == "Beenden":
            self.hide()
            self.app.quit()

if __name__ == "__main__":
    app = QApplication([])
    st = SystemTray(app)
    st.show()
    app.exec_()

Das Programm läuft Fehlerfrei, der/das ToolTip wird angezeigt, nur das Kontextmenü ist praktisch nicht vorhanden. Soll heißen weder linke noch rechte Maustaste zeigen irgendeine Wirkung.
Benutze Python 2.5 und PyQt 4.7.2.
Dies ist keine Signatur!
ichisich
User
Beiträge: 134
Registriert: Freitag 1. Januar 2010, 11:52

Hi,
ich vermute mal Du musst die
contextMenuPolicy
noch setzen !?

Gruß

#edit:
von deinem Menu wenn dann. Oder ich bin auch auf dem Holzweg.

#edit 2:
ich bin auf dem Holzeweg ...
Tut so nicht. KP sonst ..
Gruß
ichisich
User
Beiträge: 134
Registriert: Freitag 1. Januar 2010, 11:52

Ha jetzt doch noch ...
hier gefunden ...

Du mußt dem menu-Objekt ein Parent übergeben sonst gehts nicht.

Code: Alles auswählen

from PyQt4.QtGui import *
from PyQt4.Qt import Qt

class SystemTray(QSystemTrayIcon):

    def __init__(self, app, parent = None):
        QSystemTrayIcon.__init__(self, parent)
        self.app = app

        self.setIcon(QIcon( r"C:\Python25\CreateNic Test\GUI\Res\icon-taskleiste.png"))
        
        menu = QMenu(parent)
        
        menu.addAction("Einstellungen")
        menu.addAction("Bugbericht senden")
        menu.addAction("Hilfe")
        menu.addSeparator()
        menu.addAction("Beenden")
       
        self.setContextMenu(menu)
        self.setToolTip("CreateNic DesktopPanel (Version 1.0)")
        self.contextMenu().triggered.connect(self.triggered)

    def triggered(self, action):
        if action.text() == "Beenden":
            self.hide()
            self.app.quit()

if __name__ == "__main__":
    app = QApplication([])
    w = QWidget()
    st = SystemTray(app, w)
    st.show()
    app.exec_()
Shaldy
User
Beiträge: 123
Registriert: Sonntag 2. März 2008, 22:49

Okay, funktioniert, aber wenn die das Programm beende kommt ne Fehlermeldung von Windows: "pythonw.exe funktioniert nicht mehr".

Das hab ich fast immer bei PyQt Anwendungen und bekomms meist mit nem expliziten app.quit() in den Griff. Hier aber nicht. Woran liegt das überhaupt?
Dies ist keine Signatur!
ichisich
User
Beiträge: 134
Registriert: Freitag 1. Januar 2010, 11:52

In dem Code den Du hier gepostet hast ?
Hmm, kann ich so nicht bei mir nachvollziehen.
Evt. solltest Du das mal durch debuggen wo deine App nicht sauber beendet wird.

Gruß
Shaldy
User
Beiträge: 123
Registriert: Sonntag 2. März 2008, 22:49

Code: Alles auswählen

from PyQt4.QtGui import *

class SystemTray(QSystemTrayIcon):

    def __init__(self, app, parent = None):
        QSystemTrayIcon.__init__(self, parent)
        self.app = app

        self.setIcon(
            QIcon( r"C:\Python25\CreateNic Test\GUI\Res\icon-taskleiste.png" )
            )

        menu = QMenu(parent)
        menu.addAction("Einstellungen")
        menu.addAction("Bugbericht senden")
        menu.addAction("Hilfe")
        menu.addSeparator()
        menu.addAction("Beenden")
        
        self.setContextMenu(menu)
        self.setToolTip("CreateNic DesktopPanel (Version 1.0)")
        self.contextMenu().triggered.connect(self.triggered)

    def triggered(self, action):
        if action.text() == "Beenden":
            self.hide()
            self.app.quit()

if __name__ == "__main__":
    app = QApplication([])
    w = QWidget()
    st = SystemTray(app, w)
    st.show()
    app.exec_()
Hier schmiert mir der Debugger ab:

Code: Alles auswählen

self.contextMenu().triggered.connect(self.triggered)
Also "Das Programm reagiert nicht.

EDIT: Habs nochmal debuggt, jetzt geht er ganz durch, nach app.quit() kommt die Meldung aber trotzdem...
Dies ist keine Signatur!
ichisich
User
Beiträge: 134
Registriert: Freitag 1. Januar 2010, 11:52

Also ich kann es leider nicht nachvollziehen und weiß auch nicht ganz warum was falsch laufen sollte.

Passiert das auch wenn Du das Skript per python.exe vom der CMD aus startest oder nur aus der IDE ?
Shaldy
User
Beiträge: 123
Registriert: Sonntag 2. März 2008, 22:49

Das Problem tritt immer auf, selbst, wenn ich ne Standalone exe mit py2exe mache :/
Bei meinen anderen PyQt Programmen tritt das Problem aber nur teilweise auf. Manchmal hab ich das Gefühl, es ist komplett verschwunden und dann ist es auf einmal wieder ständig...

Zur Sicherheit mal meine PC Daten:

Laptop: Toshiba Satellite L300D
OS: Windows x86 Vista Home Premium
Prozessor: AMD Sempron
Grafik: ATI Radeon 3100 Graphics

Btw, bei normalen Pythoncodes tritt dieses Problem niemals auf!
Dies ist keine Signatur!
lunar

@shaldy: Nicht zum Problem, aber zum Code:
  • Es ist nicht nötig, dass QApplication-Objekt explizit durchzureichen. Daran kommst Du auch mit "QApplication.instance()".
  • Der Text-Vergleich, um den gewählten Menüeintrag herauszubekommen, ist absolut unschön! Verwende das "triggered"-Signal der Action, nicht das Signal des Menü-Objekts, dann kannst Du Dir auch die Slot-Methode sparen. Das geht dann so:

    Code: Alles auswählen

    quit_action = menu.addAction('Beenden')
    quit_action.triggered.connect(QApplication.instance().quit)
    QApplication.instance().aboutToQuit.connect(self.hide)
    So erreichst Du, dass ein Klick auf Beenden die Anwendung schließt, und das Trayicon vor dem Beenden der Anwendung ausgeblendet wird.
Shaldy
User
Beiträge: 123
Registriert: Sonntag 2. März 2008, 22:49

Danke, das mit QApplication.instance() war sehr hilfreich :D

Kann mir jetzt noch irgendjemand sagen, warum nach Beenden des Programms immer diese Meldung kommt?
Dies ist keine Signatur!
ichisich
User
Beiträge: 134
Registriert: Freitag 1. Januar 2010, 11:52

Das Problem tritt immer auf, selbst, wenn ich ne Standalone exe mit py2exe mache :/
Das machts nicht einfacher, im Gegenteil denke ich.

Was ich bei so was meist mache ist mir so:

Code: Alles auswählen

app.exec_()
print "Programm erfolgreich beendet"
raw_input("Enter zum Beenden")
eine Ausgabe printen und mit "Enter" Beenden lassen um auszuschliessen das ich irgendwo die Rückgaben falsch behandel.

Vielleicht siehst Du ja dann ob das Programm nach app.exec_() immer sauber weiterläuft oder der Fehler doch schon früher auftaucht.

Als zweiten Punkt würde ich es mal aus der Konsole heraus starten mit:

Code: Alles auswählen

python.exe deinSkript.py 
und nix mit py2exe etc.


Mehr einfallen tut mir aber momentan auch nicht.
Bei XP und W7 tuts bei mir. Vista kann ich nicht testen.

Gruß
Shaldy
User
Beiträge: 123
Registriert: Sonntag 2. März 2008, 22:49

Hab seid 2 Tagen Win7 32bit da kommt der Fehler nicht mehr so oft, aber trotzdem...
Dies ist keine Signatur!
Antworten