我有一个跨平台应用程序,它有一个坐在托盘中的gtk.StatusIcon,以及一个右键单击上下文菜单。问题是:在Windows机器上,菜单的放置很糟糕。菜单顶部从鼠标指针开始,因此大部分菜单都延伸到屏幕底部。然后可以向上滚动并且可以使用它,但这对用户来说有点痛苦。
另一个相关问题是,如果用户点击屏幕上的其他位置,是否可以使菜单消失?
答案 0 :(得分:3)
要避免Windows上的“滚动菜单”问题,您需要在“弹出菜单”信号回调中将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
答案 1 :(得分: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的调用有点不稳定,所以定时器是必要的。
BTW,这实际上只在Windows中是必需的,因为在Linux中你可以点击其他地方,弹出窗口将会关闭。答案 2 :(得分: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顶级窗口并抓住焦点,并在焦点时添加破坏功能。