2011-03-07 38 views
3
#submenu 
    clearMenu = gtk.Menu() 

    item = gtk.MenuItem("submenu item") 
    item.connect("activate", lambda w: self.callBackFunction()) 
    clearMenu.append(item) 
    item.show() 


    '''TOP level''' 
    menu = gtk.Menu() 

    item = gtk.ImageMenuItem("Item1") 
    img = gtk.Image() 
    img.set_from_file('image1.png') 
    item.set_image(img) 
    menu.append(item) 
    item.set_submenu(clearMenu) #attach submenu 
    item.show() 

    item = gtk.ImageMenuItem("Item2") 
    img = gtk.Image() 
    img.set_from_file('image2.png') 
    item.set_image(img) 
    item.connect("activate", lambda w: self.callBackFunction()) 
    menu.append(item) 
    item.show() 

我的頂級項目「Item2」調用定義的函數「callBackFunction」。但爲什麼「子菜單項」不是? 我做錯了什麼?子菜單項不呼叫功能[帶有工作解決方案]


編輯

這裏是如何我已經成功地迫使子菜單項跳入所需的操作:

item.connect("button-press-event", self.callBackFunction, argument1, argument2) 

但我仍然不明白爲什麼事件「激活」呢不適用於子菜單項,而在頂級菜單項中工作

+0

難道是你只是拼寫錯誤的子菜單項上的信號「激活」? – 2011-03-07 15:44:18

+0

我試圖複製到非工作位置的工作線 - 仍然沒有效果: -/ – Lixas 2011-03-07 19:04:24

+0

它變得更加陌生:如果我使用鍵盤導航進行_left鼠標button_菜單導航,它會起作用。但是如果我使用鼠標,它不會觸發子菜單事件 – Lixas 2011-03-08 06:49:47

回答

4

這是子菜單焦點的固有問題explained here

子菜單中沒有得到焦點,直到它連接到被點擊菜單項(即使當鼠標移動到菜單項出現的子菜單。)

其結果是,在各子項菜單不會發出激活信號,除非先單擊父菜單項。

這解釋了爲什麼鍵盤導航似乎工作。

我一直在解決這個問題已經有一年多的時間了,我不知道任何解決方案 - 只是你發現的"button-press-event"解決方法。

4

雖然"button-press-event"作品,它有幾個缺點:

  • 它不僅供鍵盤導航
  • 如果回調塊,整個X服務器被封鎖的工作(見gPodder bug 1778

對於我自己的應用程序(gPodder),我已經在commit a09b204a中解決了這個問題。

我們所希望的:

  1. 作出反應,"activate"信號(鍵盤導航和情況下的父菜單項也點擊)
  2. 反應的"button-press-event"信號(來解決的bug)
  3. 運行在未來的主循環迭代回調(以避免阻塞X服務器)
  4. 確保回調時才調用("activate""button-press-event"可以以秒都發生ome情況下)

對於1.和2.我們可以簡單地連接到兩個信號。 對於3.我們可以使用gobject.idle_add()。 對於4.我們可以使用threading.Semaphore

這導致下面的代碼:

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) 

你可以在你的代碼如下現在使用這樣的:與其說之一:

item.connect("activate", lambda w: self.callBackFunction()) 
item.connect("button-press-event", self.callBackFunction, argument1, argument2) 

你,而不是把這個:

submenu_item_connect_hack(item, self.callBackFunction, argument1, argument2) 

另外,在GNOME Bugzilla中的filed bug 695488