pynotify:“封闭”信号回调永远不会被解雇

时间:2011-12-23 11:03:13

标签: python pynotify libnotify

我正在尝试使用pynotify编写程序,这是用于libnotify的Python绑定。我想在某个时刻提出关键通知,并在信息发生变化时每隔几秒更新一次,直到用户点击它为止。这一切都有效,除了处理用户解雇时发生的事情。

要更新通知,我需要在Notification.show之后致电Notification.update。这很好,但这意味着我需要跟踪用户是否已经解除了通知,否则它会再次弹出。

这应该是我能想到的两种方法:

  1. 检测通知是否可见。我还没有找到任何解决方法。
  2. 在通知关闭时存储一些变量,然后在更新之前检查它并再次调用Notification.show
  3. 第二种方法应该是可行的。我找到的示例代码(似乎没有任何适当的pynotify文档)让我调用Notification.connect"closed"信号连接到回调。我试图这样做,但回调从未被解雇。

    我用Google搜索并调试了很长时间但无法取得任何进展。最后我发现了一些带有pynotify的示例脚本。其中一个将处理程序附加到"closed"信号:test-xy-stress.py

    其内容如下:

    #!/usr/bin/env python
    
    import pygtk
    pygtk.require('2.0')
    import gobject
    import gtk
    import gtk.gdk
    import pynotify
    import sys
    import random
    
    exposed_signal_id = 0
    count = 0
    
    def handle_closed(n):
        print "Closing."
    
    def emit_notification(x, y):
        n = pynotify.Notification("X, Y Test",
            "This notification should point to %d, %d." % (x, y))
        n.set_hint("x", x)
        n.set_hint("y", y)
        n.connect('closed', handle_closed)
        n.show()
    
    def popup_random_bubble():
        display = gtk.gdk.display_get_default()
        screen = display.get_default_screen()
        screen_x2 = screen.get_width() - 1
        screen_y2 = screen.get_height() - 1
    
        x = random.randint(0, screen_x2)
        y = random.randint(0, screen_y2)
        emit_notification(x, y)
        return True
    
    
    if __name__ == '__main__':
        if not pynotify.init("XY Stress"):
            sys.exit(1)
    
        gobject.timeout_add(1000, popup_random_bubble)
    
        gtk.main()
    

    我跑了这个,发现这里的回调也不会发生。

    这可能只是我的系统,还是pynotify或libnotify中有错误?如果现在这个问题无法解决,那么上面的选项1是什么呢?有什么方法可以做到这一点吗?

    我似乎有libnotify 0.4.5和pynotify 0.1.1。

2 个答案:

答案 0 :(得分:2)

我一直在寻找同样的事情。我发现有人使用gobject.MainLoop而不是gtk.main来帮助:linuxquestions.org

我发现这对我有用:

#!/usr/bin/python

import pynotify
import gobject

def OnClicked(notification, signal_text):
    print '1: ' + str(notification)
    print '2: ' + str(signal_text)
    notification.close()
    global loop
    loop.quit()

def OnClosed(notification):
    print 'Ignoring fire'
    notification.close()
    global loop
    loop.quit()

def Main():
    pynotify.init('ProgramName')

    global loop
    loop = gobject.MainLoop()

    notify = pynotify.Notification('Fire!', 'I\'m just kidding...')
    # optionalm, just changes notification color
    notify.set_urgency(pynotify.URGENCY_CRITICAL)
    # optional, it will expire eventually
    notify.set_timeout(pynotify.EXPIRES_NEVER)

    notify.add_action('You Clicked The Button', 'Remove Fire', OnClicked)
    notify.connect("closed",OnClosed)

    notify.show()

    loop.run()

if __name__ == '__main__':
    Main()

答案 1 :(得分:0)

尝试以下方法:

添加:

from time import  sleep

并在您的emit_notification结束时:

sleep(2)
n.close()

(与OP讨论后更新:) 这应该会激活你的回调!这样,如果您的DBus-Server执行了它应该执行的操作,您可以与dbus-monitor一起进行测试。 (来自OP的想法。)

这仍然不是你真正想要的,但暂时至少解释了你对未发出信号的困惑。

你可能应该研究的是动作属性。我找到了一些有趣的东西here。您似乎可以直接在通知中与用户进行互动。

因为pynotify只是DBus通信的包装器,所以您也可以尝试一种解决方法:

from dbus import SessionBus, Interface
from dbus.mainloop.glib import DBusGMainLoop
DBusGMainLoop(set_as_default=True)

notify_busname = 'org.freedesktop.Notifications'
notify_obj_path ='/org/freedesktop/Notifications'
lbus = SessionBus()

notify_server = lbus.get_object(notify_busname, notify_obj_path)

并在你的处理程序定义之后:

notify_server.connect_to_signal(None, handle_closed)

我还为测试目的更改了函数的签名以适合DBus信号:

def handle_closed(*arg, **kwargs):