gtk.StatusIcon и gtk.Menu в Windows

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

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


person wodemoneke    schedule 16.07.2009    source источник


Ответы (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.

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

person Ivan Baldin    schedule 16.07.2009
comment
большое спасибо! Эта другая проблема не такая уж большая проблема, я думаю, я могу жить с ней. - person wodemoneke; 16.07.2009

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

person jcoffland    schedule 17.07.2010

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

person General Milk    schedule 11.07.2017