1

libnotify の Python バインディングである pynotify を使用してプログラムを作成しようとしています。ある時点で重要な通知を表示し、ユーザーがクリックするまで、情報の変更に応じて数秒ごとに更新したいと考えています。これは、ユーザーがそれを閉じたときに何が起こるかを処理することを除いて、すべて機能します。

通知を更新するには、 のNotification.show後に呼び出す必要がありますNotification.update。それは問題ありませんが、ユーザーが通知を閉じたかどうかを追跡する必要があることを意味します。そうしないと、再びポップアップし続けるだけです。

それは、私が考えることができる2つの方法で可能になるはずです:

  1. 通知が表示されているかどうかを検出します。私はそれを見つける方法を見つけていません。
  2. 通知が閉じられたときにいくつかの変数を保存し、更新してNotification.show再度呼び出す前に確認します。

この 2 番目の方法は可能です。私が見つけたコード例 (pynotify に関する適切なドキュメントはないようです) により、シグナルをコールバックNotification.connectに接続するために呼び出すことができました。"closed"私はそれをやろうとしましたが、コールバックは決して発生しませんでした。

私は長い間グーグルでデバッグしましたが、何の進展もありませんでした。最終的に、pynotify に付属するサンプル スクリプトをいくつか見つけました。そのうちの 1 つは、ハンドラーを"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

私は同じものを探してきました。助けてくれる gtk.main の代わりに gobject.MainLoop を使っている人を見つけました: 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-Server が本来の動作を行っているかどうかを dbus-monitor と一緒にテストできます。(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 に答える