gtk.StatusIcon и gtk.Menu для Windows - PullRequest
4 голосов
/ 16 июля 2009

У меня есть кроссплатформенное приложение с gtk.StatusIcon в трее и контекстным меню правой кнопкой мыши. Проблема в том, что на компьютерах с Windows расположение меню ужасное. Верхняя часть меню начинается с указателя мыши, поэтому большая часть меню располагается ниже нижней части экрана. Затем его можно прокрутить и использовать, но это немного болезненно для пользователя.

Еще один связанный с этим вопрос, возможно ли заставить меню исчезнуть, если пользователь щелкнет где-то еще на экране?

Ответы [ 3 ]

3 голосов
/ 16 июля 2009

Чтобы избежать этой проблемы с «меню прокрутки» в 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.

Не знаю, как скрыть это, хотя ... единственное, что я нашел для работы, - это нажать кнопку мыши в меню и отпустить ее снаружи. : Р

2 голосов
/ 17 июля 2010

Вы можете скрыть всплывающее окно, когда мышь удаляется, включив в нем события left_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 и left_notify несколько ошибочны, поэтому необходим таймер.

Кстати, это действительно необходимо только в Windows, потому что в Linux вы можете щелкнуть в другом месте, и всплывающее окно закроется.

1 голос
/ 12 июля 2017

Я нашел решение, чтобы исправить всплывающее меню, не скрывающее проблему в 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 в позиции мыши, захватить фокус и добавить функцию уничтожения при фокусировке.

...