<p>虽然<code>"button-press-event"</code>起作用,但它有一些缺点:</p>
<ul>
<li>它不适用于纯键盘导航</li>
<li>如果回调阻塞,则整个X服务器被阻塞(参见<a href="http://gpodder.org/bug/1778" rel="nofollow">gPodder bug 1778</a>)</li>
</ul>
<p>对于我自己的应用程序(gPodder),我已经在<a href="http://gpodder.org/commit/a09b204a" rel="nofollow">commit a09b204a</a>中解决了这个问题。在</p>
<p>我们想要的:</p>
<ol>
<li>对<code>"activate"</code>信号作出反应(对于键盘导航和父菜单项也被单击的情况)</li>
<li>对<code>"button-press-event"</code>信号作出反应(以解决错误)</li>
<li>在下一个主循环迭代中运行回调(以避免阻塞X服务器)</li>
<li>确保回调只被调用一次(<code>"activate"</code>和{<cd1>}在某些情况下都可能发生)</li>
</ol>
<p>为1。和2。我们可以简单地连接两个信号。
为3。我们可以使用<code>gobject.idle_add()</code>。
为4。我们可以使用<code>threading.Semaphore</code>。在</p>
<p>这将导致以下代码:</p>
<pre><code>import threading
import gobject
def submenu_item_connect_hack(menu_item, callback, *args_for_callback):
only_once = threading.Semaphore(1)
def handle_event(item, event=None):
if only_once.acquire(False):
gobject.idle_add(callback, *args_for_callback)
menu_item.connect('button-press-event', handle_event)
menu_item.connect('activate', handle_event)
</code></pre>
<p>现在,可以在代码中按如下方式使用它:而不是调用其中一个:</p>
^{pr2}$
<p>你改为这样叫:</p>
<pre><code>submenu_item_connect_hack(item, self.callBackFunction, argument1, argument2)
</code></pre>
<p>还有,GNOME Bugzilla中的<a href="https://bugzilla.gnome.org/show_bug.cgi?id=695488" rel="nofollow">filed bug 695488</a>。在</p>