2009-07-16 46 views
4

我有一个跨平台的应用程序,它具有一个坐在托盘中的gtk.StatusIcon和一个右键单击上下文菜单。问题是:在Windows机器上,菜单的位置很糟糕。菜单的顶部从鼠标指针开始,因此大部分菜单延伸到屏幕底部以下。然后可以向上滚动并且可用,但对用户来说有点痛苦。gtk.StatusIcon和Windows上的gtk.Menu

另一个相关的问题是,如果用户点击屏幕上的其他位置,菜单是否可以消失?

回答

3

为了避免Windows上的“滚动菜单”问题,您需要在“popup-menu”信号回调中将gtk.status_icon_position_menu替换为None

def popup_menu_cb(status_icon, button, activate_time, menu): 
    menu.popup(None, None, None, button, activate_time) 

菜单显示在鼠标光标但这是所有Windows程序是怎么做的。

不知道如何隐藏它...我发现唯一的工作是按下菜单上的鼠标按钮并将其释放到外面。 :P

+0

太好了,谢谢! 这个其他问题并不是什么大不了的,我想我可以忍受它。 – wodemoneke 2009-07-16 18:11:38

2

通过在弹出窗口中启用leave_notify和enter_notify事件,您可以在鼠标移开时隐藏弹出窗口。然后使用这些设置和清除时间戳。然后,在用gobject.timeout_add()创建的计时器回调中,检查鼠标是否已经离开弹出菜单一段时间。如果它已经隐藏()弹出并清除计时器。

这里是事件和计时器回调我使用:

. . . 
    self.mouse_in_tray_menu = None 
    gobject.timeout_add(500, self.check_hide_popup) 
. . . 

def on_tray_menu_enter_notify_event(self, widget, event, data = None): 
    self.mouse_in_tray_menu = None 


def on_tray_menu_leave_notify_event(self, widget, event, data = None): 
    self.mouse_in_tray_menu = event.time + 1 # Timeout in 1 sec 


def check_hide_popup(self, data = None): 
    if self.mouse_in_tray_menu and self.mouse_in_tray_menu < time.time(): 
     self.tray_menu.hide() 
     self.mouse_in_tray_menu = None 

    return True # Keep the timer callback running 

你不必保持定时器运行所有的时间,但它很容易,我也使用它的其他东西。对enter_notify和leave_notify的调用有些不稳定,所以定时器是必需的。

顺便说一句,这只是在Windows中必需的,因为在Linux中您可以单击其他地方,弹出窗口将关闭。

1

我发现一个解决方案来修复弹出菜单不会隐藏在Windows上的问题。

只需添加如下代码(我的代码是C,但你可以把它改成Python或其他)弹出菜单前:

GtkWidget *hidden_window; 
hidden_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); 
gtk_window_set_resizable (GTK_WINDOW (hidden_window), FALSE); 
gtk_window_set_decorated (GTK_WINDOW (hidden_window), FALSE); 
gtk_window_set_skip_taskbar_hint (GTK_WINDOW (hidden_window), TRUE); 
gtk_window_set_skip_pager_hint (GTK_WINDOW (hidden_window), TRUE); 
gtk_widget_set_size_request (hidden_window, 0, 0); 
gtk_window_set_transient_for (GTK_WINDOW (hidden_window), GTK_WINDOW (widget)); //widget is your main window, this is to hide dummy window from taskbar 
gtk_window_set_position (GTK_WINDOW (hidden_window), GTK_WIN_POS_MOUSE); 

gtk_widget_set_events (hidden_window, GDK_FOCUS_CHANGE_MASK); 
g_signal_connect (G_OBJECT (hidden_window), 
       "focus-out-event", 
       G_CALLBACK (on_hidden_window_focus_out), 
       NULL); 
gtk_widget_show_all (hidden_window); 
gtk_widget_grab_focus (hidden_window); 

还添加此功能:

static void on_hidden_window_focus_out(GtkWidget *widget, 
       GdkEventFocus *event, 
       gpointer data) 
{ 
    gtk_widget_destroy (widget); 
} 

的想法是在鼠标位置创建一个1x1顶层窗口并抓住焦点,并在焦点出来时添加破坏功能。