【问题标题】:pynotify: "closed" signal callback never firedpynotify:“关闭”信号回调从未触发
【发布时间】:2012-01-26 08:41:51
【问题描述】:

我正在尝试使用 pynotify(libnotify 的 Python 绑定)编写程序。我想在某个时候提出一个重要通知,并随着信息的变化每隔几秒钟更新一次,直到用户点击它。除了处理用户关闭它时发生的事情之外,这一切都有效。

为了更新通知,我需要在Notification.update 之后调用Notification.show。没关系,但这意味着我需要跟踪用户是否关闭了通知,否则它会再次弹出。

这应该可以通过我能想到的两种方法来实现:

  1. 检测通知是否可见。我还没有找到任何方法来解决这个问题。
  2. 在通知关闭时存储一些变量,然后在更新之前检查它并再次调用Notification.show

第二种方法应该是可行的。我发现的示例代码(似乎没有任何适当的 pynotify 文档)导致我调用 Notification.connect 以将 "closed" 信号连接到回调。我尝试这样做,但从未触发回调。

我用谷歌搜索和调试了很长时间,但没有任何进展。最终我找到了一些 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。

【问题讨论】:

    标签: python pynotify libnotify


    【解决方案1】:

    我一直在寻找同样的东西。我发现有人使用 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()
    

    【讨论】:

    • 就我而言,问题消失了,我知道原因。如果我有时间我会调查——它一定是一个不相关的补丁,它在某个时候做了它。不过,很高兴它对你有用。
    【解决方案2】:

    尝试以下方法:

    添加:

    from time import  sleep
    

    在您的 emit_notification 结束时:

    sleep(2)
    n.close()
    

    (在与 OP 讨论后更新:) 这应该会触发您的回调!这样你就可以和 dbus-monitor 一起测试,如果你的 DBus-Server 做了它应该做的事情。 (来自 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):
    

    【讨论】:

    • 不,我仍然没有得到“关闭”。我的终端上的消息,这是这个测试脚本中的回调应该做的。你收到那些消息了吗?看看specification for the "closed" signal,它说我们应该在通知关闭时收到"closed"信号,无论通知是否过期、用户关闭它或我们调用Notification.close
    • 是的,我确实收到了消息! libnotify/pynotify 库是 DBus-Communication 的包装器。所以必须有一个合适的 DBus-Server 来正确处理你的 DBus-Clients 请求。只是在同一页面上:您正在使用什么系统?
    • Ubuntu 10.04 x86_64。根据规范,您建议的更改(调用Notification.close 方法)不应该有所作为——无论哪种方式,您都应该得到"closed" 信号。你能仔细检查一下吗?我想知道为什么它对我不起作用。
    • 我刚才尝试运行 dbus-monitor 并观察会发生什么。发出通知时我看到了 DBus 通信,但是当它们消失或者我单击它们或其他什么时没有通信。当您的通知消失时,您能否查看是否有任何 DBus 消息移动?
    • 是的,我愿意!示例性 dbus-monitor-sn-p:“signal sender=:1.143 -> dest=:1.166 serial=320 path=/org/freedesktop/Notifications; interface=org.freedesktop.Notifications; member=NotificationClosed” 没有强制关闭-方法调用!
    猜你喜欢
    • 2013-05-10
    • 2011-10-30
    • 1970-01-01
    • 2019-04-18
    • 1970-01-01
    • 1970-01-01
    • 2012-07-31
    • 2011-09-21
    • 1970-01-01
    相关资源
    最近更新 更多