PyQt4 托盘图标显示 QLabel 时出现问题

发布于 2024-10-22 01:54:40 字数 2176 浏览 2 评论 0原文

当以下代码运行时,托盘应用程序可以在屏幕中间弹出 AboutWindow QLabel 对象。但是,当关闭此屏幕时,整个应用程序将关闭,没有任何错误(托盘图标消失,控制台日志没有显示任何错误)。

import sys
from PyQt4 import QtGui, QtCore


class AboutWindow(QtGui.QLabel):

def __init__(self, parent=None):
    QtGui.QLabel.__init__(self, parent=parent)
    self.setText("""
    Huge text goes here
    """)


class SystemTrayIcon(QtGui.QSystemTrayIcon):
    def __init__(self, icon, parent=None):
        QtGui.QSystemTrayIcon.__init__(self, icon, parent)
        menu = QtGui.QMenu(parent)
        self.createMenuActions(menu)
        self.setContextMenu(menu)
        # I've tried using the same parent as QSystemTrayIcon, 
        # but the label is not shown.
        # self.aboutWindow = AboutWindow(parent=parent)
        self.aboutWindow = AboutWindow(parent=None)


    def createMenuActions(self, menu):
        exitAction = QtGui.QAction("Exit", menu)
        configureAppAction = QtGui.QAction("Configure Application", menu)
        aboutAction = QtGui.QAction("About", menu)

        self.connect(configureAppAction, QtCore.SIGNAL('triggered()'), self._configureApp)
        self.connect(aboutAction, QtCore.SIGNAL('triggered()'), self._showAbout)
        self.connect(exitAction, QtCore.SIGNAL('triggered()'), self._exitApp)

        self.addActionsToMenu(menu, configureAppAction, aboutAction, exitAction)

    def addActionsToMenu(self, menu, *args):
        for action in args:
            menu.addAction(action)

    def _configureApp(self): pass

    def _showAbout(self):
        self.aboutWindow.show()

    def _exitApp(self):
        sys.exit(0)

def main():
    app = QtGui.QApplication(sys.argv)
    widget = QtGui.QWidget()
    # I'm passing a widget parent to QSystemTrayIcon as pointed out in:
    # http://stackoverflow.com/questions/893984/pyqt-show-menu-in-a-system-tray-application
    trayIcon = SystemTrayIcon(QtGui.QIcon("icon.xpm"), widget)
    trayIcon.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

正如代码中所指出的,我尝试为托盘图标和 AboutWindow 对象设置相同的父级,但这不起作用(标签未显示)。我也尝试过子类化 QMainWindow,但出现了相同的效果。

我想了解当窗口和图标都不共享相同父级时从 QSystemTrayIcon 打开新窗口时这是否是默认行为,以及是否有解决方法。

谢谢。

When the following code runs, the tray application can pop-up the AboutWindow QLabel object in the middle of screen. But when closing this screen, the whole application is shutdown with no errors (the tray icon disappears and the console log shows no error whatsoever).

import sys
from PyQt4 import QtGui, QtCore


class AboutWindow(QtGui.QLabel):

def __init__(self, parent=None):
    QtGui.QLabel.__init__(self, parent=parent)
    self.setText("""
    Huge text goes here
    """)


class SystemTrayIcon(QtGui.QSystemTrayIcon):
    def __init__(self, icon, parent=None):
        QtGui.QSystemTrayIcon.__init__(self, icon, parent)
        menu = QtGui.QMenu(parent)
        self.createMenuActions(menu)
        self.setContextMenu(menu)
        # I've tried using the same parent as QSystemTrayIcon, 
        # but the label is not shown.
        # self.aboutWindow = AboutWindow(parent=parent)
        self.aboutWindow = AboutWindow(parent=None)


    def createMenuActions(self, menu):
        exitAction = QtGui.QAction("Exit", menu)
        configureAppAction = QtGui.QAction("Configure Application", menu)
        aboutAction = QtGui.QAction("About", menu)

        self.connect(configureAppAction, QtCore.SIGNAL('triggered()'), self._configureApp)
        self.connect(aboutAction, QtCore.SIGNAL('triggered()'), self._showAbout)
        self.connect(exitAction, QtCore.SIGNAL('triggered()'), self._exitApp)

        self.addActionsToMenu(menu, configureAppAction, aboutAction, exitAction)

    def addActionsToMenu(self, menu, *args):
        for action in args:
            menu.addAction(action)

    def _configureApp(self): pass

    def _showAbout(self):
        self.aboutWindow.show()

    def _exitApp(self):
        sys.exit(0)

def main():
    app = QtGui.QApplication(sys.argv)
    widget = QtGui.QWidget()
    # I'm passing a widget parent to QSystemTrayIcon as pointed out in:
    # http://stackoverflow.com/questions/893984/pyqt-show-menu-in-a-system-tray-application
    trayIcon = SystemTrayIcon(QtGui.QIcon("icon.xpm"), widget)
    trayIcon.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

As pointed out in the code, I've tried setting the same parent for the tray icon and the AboutWindow object, but that didn't work (the label is not shown). I have also tried subclassing QMainWindow, but the same effect occured.

I would like to understand if that's the default behavior when opening a new window from QSystemTrayIcon when neither the window and the icon share the same parent, and if there's a workaround for this matter.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

绝情姑娘 2024-10-29 01:54:40

好吧,我想我对这个问题不太清楚,但我找到了一个简单的解决方案。

Qt 有一个方法可以捕获分派到小部件的关闭事件 (http://doc.qt.nokia.com/4.6/qwidget.html#closeEvent)。您可以在 QWidget 子类中重写此方法以防止小部件关闭(在我的所有测试中,这将关闭整个应用程序)并仅隐藏它。下面的代码显示了我在代码中所做的更改以使其正常工作:

...

class AboutWindow(QtGui.QLabel):

    def __init__(self, parent=None):
        QtGui.QLabel.__init__(self, parent=parent)
        self.setText("""
        Huge text goes here
        """)

    # Prevent the widget from closing the whole application, only hides it
    def closeEvent(self, event):
        event.ignore()
        self.hide()

...

Alright, I guess I wasn't too clear about the problem, but I found a simple solution.

Qt has a method that captures the close event dispatched to a widget (http://doc.qt.nokia.com/4.6/qwidget.html#closeEvent). You can, in your QWidget subclass, rewrite this method to prevent the widget from closing (which, in all my tests, would close the whole application) and only hide it. The code below shows what I've changed in my code to make it work:

...

class AboutWindow(QtGui.QLabel):

    def __init__(self, parent=None):
        QtGui.QLabel.__init__(self, parent=parent)
        self.setText("""
        Huge text goes here
        """)

    # Prevent the widget from closing the whole application, only hides it
    def closeEvent(self, event):
        event.ignore()
        self.hide()

...
谁把谁当真 2024-10-29 01:54:40

出现此问题的原因是,当您关闭“唯一”窗口时,Qt 错误地认为您要退出应用程序。
你的(Kaos12)答案是一个丑陋的修复恕我直言,有时你真的想关闭这些东西(这与隐藏它不同)。
正确的方法是

app.setQuitOnLastWindowClosed(False)

在该代码的第 50 行之后(“创建”应用程序之后)添加以下行来禁用此行为。该指令将告诉 Qt 即使所有窗口都关闭也不要退出应用程序。

This problem occurs because when you close the 'only' window, Qt erroneously thinks you want to quit the application.
Your (Kaos12) answer is an ugly fix imho, sometimes you really want to close the stuff (which isn't the same as hiding it).
The proper way to do that is to disable this behaviour by adding the line:

app.setQuitOnLastWindowClosed(False)

after the line 50 in that code (after 'creating' the application). This instruction will tell Qt not to quit the application even when all the windows are closed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文