Windows上的gtk.Status图标和gtk.Menu

Windows上的gtk.Status图标和gtk.Menu,gtk,pygtk,Gtk,Pygtk,我有一个跨平台应用程序,托盘中有一个gtk.status图标,右键单击上下文菜单。问题是:在Windows机器上,菜单的位置很糟糕。菜单的顶部从鼠标指针开始,因此大多数菜单延伸到屏幕底部以下。这可以向上滚动并且是可用的,但是这对用户来说有点麻烦 另一个相关问题是,如果用户单击屏幕上的其他位置,是否可能使菜单消失?要避免Windows上的“滚动菜单”问题,您需要在“弹出菜单”信号回调中将gtk.状态图标位置菜单替换为None def popup_menu_cb(status_icon, butto

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

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

要避免Windows上的“滚动菜单”问题,您需要在“弹出菜单”信号回调中将
gtk.状态图标位置菜单
替换为
None

def popup_menu_cb(status_icon, button, activate_time, menu):
    menu.popup(None, None, None, button, activate_time)
菜单将显示在鼠标光标上,但所有windows程序都是这样做的


但我不知道如何隐藏它。。。我发现唯一有效的方法就是按下菜单上的鼠标按钮,然后将其释放到外面P

当鼠标移开时,通过在弹出窗口上启用“离开通知”和“输入通知事件”,可以隐藏弹出窗口。然后使用这些设置和清除时间戳。然后在使用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
。
托盘菜单中的self.mouse\u=无
gobject.timeout\u add(500,self.check\u hide\u弹出窗口)
. . .
def on_托盘_菜单_输入_通知_事件(self、widget、event、data=None):
托盘菜单中的self.mouse\u=无
def on_托盘_菜单_leave_notify_事件(self、widget、event、data=None):
托盘菜单中的self.mouse_=event.time+1#1秒超时
def check_hide_弹出窗口(自身,数据=无):
如果托盘菜单中的self.mouse\u和托盘菜单中的self.mouse\u
你不必让计时器一直运行,但它更容易,我也在用它做其他事情。对enter_notify和leave_notify的调用有些不稳定,因此需要计时器


顺便说一句,这只有在Windows中才有必要,因为在Linux中,您可以单击其他位置,弹出窗口将关闭。

我找到了一个解决方案,可以修复弹出菜单不会隐藏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顶级窗口,抓住焦点,并在焦点不在时添加销毁功能。

太好了,谢谢!另一个问题没什么大不了的,我想我可以接受。