1

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

为了更新通知,我需要Notification.showNotification.update. 这很好,但这意味着我需要跟踪用户是否关闭了通知,否则它会再次弹出。

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

  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。

4

2 回答 2

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()
于 2012-01-26T00:41:51.243 回答
0

尝试以下操作:

添加:

from time import  sleep

并在您的 emit_notification 结束时:

sleep(2)
n.close()

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

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

您可能应该研究的是动作属性。我在这里发现了一些有趣的东西。似乎您可以直接在通知中与用户交互。

因为 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):
于 2011-12-23T12:32:02.293 回答