2009-07-16 7 views
4

Ich habe eine Crossplatform-App, die ein gtk.StatusIcon im Tray hat, und ein Rechtsklick-Kontextmenü. Das Problem ist: auf Windows-Rechnern ist die Platzierung des Menüs schrecklich. Der obere Teil des Menüs beginnt am Mauszeiger und der größte Teil des Menüs erstreckt sich unterhalb des unteren Bildschirmrands. Dies kann dann hochgerollt werden und ist verwendbar, aber es ist ein wenig schmerzhaft für den Benutzer.gtk.StatusIcon und gtk.Menu unter Windows

Eine andere verwandte Frage, ist es möglich, das Menü verschwinden zu lassen, wenn der Benutzer irgendwo anders auf dem Bildschirm klickt?

Antwort

3

Um dieses "scrollende Menü" Problem unter Windows zu vermeiden, müssen Sie gtk.status_icon_position_menu durch None in "Popup-Menü" Signal Callback ersetzen.

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

Das Menü wird Show auf dem Cursor der Maus, aber das ist, wie alle Windows-Programme es tun.

Ich weiß nicht, wie ich es verstecken soll ... das einzige, was ich gefunden habe zu arbeiten, ist eine Maustaste auf dem Menü zu drücken und es draußen freizugeben. : P

+0

toll, danke! Dieses andere Problem ist nicht so eine große Sache, ich denke, ich kann damit leben. – wodemoneke

2

Sie können das Popup ausblenden, wenn Sie die Maus wegbewegen, indem Sie die Ereignisse leave_notify und enter_notify im Popup aktivieren. Verwenden Sie diese dann, um einen Zeitstempel festzulegen und zu löschen. Dann überprüfen Sie in einem Timer-Callback, der mit gobject.timeout_add() erstellt wurde, ob die Maus für eine bestimmte Zeit nicht im Popup-Menü war. Wenn es dann ausgeblendet wurde() das Popup und lösche den Timer.

Hier sind die Event- und Timer-Rückrufe Ich verwende:

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

Sie müssen den Timer nicht halten die ganze Zeit laufen, aber es ist einfacher, und ich bin es auch für andere Dinge verwenden . Die Aufrufe von enter_notify und leave_notify sind etwas unberechenbar, daher ist der Timer notwendig.

BTW, das ist wirklich nur notwendig in Windows, weil Sie in Linux können Sie auf eine andere Stelle klicken und das Popup wird geschlossen.

1

Ich habe eine Lösung gefunden, um das Popup-Menü zu beheben, wird das Problem auf Windows nicht verbergen.

Fügen Sie einfach folgenden Code (mein Code in C, aber Sie können es zu python ändern oder was auch immer), bevor das Menü Aufspringen:

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

fügen ebenfalls diese Funktion:

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

Die Idee ist, ein 1x1 Top-Level-Fenster an der Mausposition zu erstellen und den Fokus zu greifen, und fügen Sie zerstören Funktion hinzu, wenn der Fokus aus.