Windows 上的 gtk.StatusIcon 和 gtk.Menu

发布于 2024-07-27 03:08:20 字数 191 浏览 3 评论 0原文

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

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

I have a crossplatform app that has a gtk.StatusIcon sitting in the tray, and a right click context menu. The problem is: on Windows machines the placement of the menu is awful. The top of the menu starts at the mouse pointer and so most of the menu extends below the bottom of the screen. This can then be scrolled up and is usable, but it is a bit of a pain for the user.

Another related question, is it possible to make the menu disappear if the user clicks somewhere else on the screen?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

黎歌 2024-08-03 03:08:20

为了避免 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

To avoid this "scrolling menu" problem on Windows you need to replace gtk.status_icon_position_menu with None in "popup-menu" signal callback.

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

The menu will show on the mouse cursor but that's how all windows programs do it.

Don't know how to hide it though... the only thing I found to work is pressing a mouse button on the menu and releasing it outside. :P

谜兔 2024-08-03 03:08:20

通过启用弹出窗口上的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 中,您可以单击其他地方,弹出窗口将关闭。

You can hide the popup when the mouse moves away by enabling the leave_notify and enter_notify events on the popup. Then use these to set and clear a time stamp. Then in a timer callback created with gobject.timeout_add() check to see if the mouse has been away from the popup menu for a certain amount of time. If it has then hide() the popup and clear the timer.

Here are the event and timer call backs I'm using:

. . .
    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

You don't have to keep the timer running all the time but it is easier and I am also using it for other things. The calls to enter_notify and leave_notify are somewhat erratic so the timer is necessary.

BTW, this is really only necessary in Windows because in Linux you can click elsewhere and the popup will close.

冧九 2024-08-03 03:08:20

我找到了解决 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 顶级窗口并抓住焦点,然后添加焦点移出时销毁功能。

I found a solution to fix the popup menu won't hide problem on windows.

Just add following code (my code is in C but you can change it to python or whatever) before popping up the menu:

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);

also add this function:

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

The idea is to create a 1x1 top level window at mouse position and grab the focus, and add destroy function when focus out.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文