代码之家  ›  专栏  ›  技术社区  ›  Hanlon

设置快捷键上菜单项的状态

  •  0
  • Hanlon  · 技术社区  · 6 年前

    但是,还有一个与该菜单项相关联的快捷方式。仅当菜单项处于启用状态时,快捷方式才起作用。

    当我们想使用快捷方式时,如何在不单击保存菜单项的菜单的情况下设置菜单项的状态?

    下面是一个示例程序,希望能让我的问题更清楚:

    #include <gtk/gtk.h>
    
    struct check_sensitivity
    {
            GtkWidget *menuitem;
            GtkTextBuffer *buffer;
    };
    
    void sensitivity(GtkWidget *menu, struct check_sensitivity *sens)
    {
            if (gtk_text_buffer_get_modified(sens->buffer))
                    gtk_widget_set_sensitive(sens->menuitem, TRUE);
            else
                    gtk_widget_set_sensitive(sens->menuitem, FALSE);
    }
    
    void menuitem_click(GtkWidget *menuitem, GtkTextBuffer *buffer)
    {
            gtk_text_buffer_set_text(buffer, "", -1);
            gtk_text_buffer_set_modified(buffer, FALSE);
    }
    
    int main(int argc, char **argv)
    {
            gtk_init(&argc, &argv);
    
            struct check_sensitivity sens;
    
            GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
            g_signal_connect(window, "delete-event", G_CALLBACK(gtk_main_quit), NULL);
    
            GtkWidget *view = gtk_text_view_new();
            sens.buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
    
            GtkWidget *menubar = gtk_menu_bar_new();
            GtkWidget *menu = gtk_menu_new();
    
            GtkAccelGroup *shortcuts = gtk_accel_group_new();
            gtk_window_add_accel_group(GTK_WINDOW(window), shortcuts);
    
            GtkWidget *menuitem = gtk_menu_item_new_with_label("Menu");
            gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menu);
            gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menuitem);
            g_signal_connect(menuitem, "activate", G_CALLBACK(sensitivity), &sens);
            menuitem = gtk_menu_item_new_with_label("Clear");
            gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
            gtk_widget_add_accelerator(menuitem, "activate", shortcuts, GDK_KEY_D, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
            sens.menuitem = menuitem;
            g_signal_connect(sens.menuitem, "activate", G_CALLBACK(menuitem_click), sens.buffer);
    
            GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
            gtk_box_pack_start(GTK_BOX(box), menubar, FALSE, FALSE, 0);
            gtk_box_pack_start(GTK_BOX(box), view, TRUE, TRUE, 0);
    
            gtk_container_add(GTK_CONTAINER(window), box);
    
            gtk_widget_show_all(window);
    
            gtk_main();
    }
    

    在这个程序中,菜单项“清除”的状态取决于缓冲区是否被修改。当然,当用户单击菜单“menu”时,状态就设置好了。

    这和点击“清除”是一样的。快捷方式的工作方式取决于菜单项的状态,但错误的是菜单项的状态。让我解释一下:

    由于菜单项是在用户单击“菜单”时(取消)设置的,要在使用快捷方式之前更新“清除”状态,用户必须单击它。如果在更新菜单项的状态之前使用快捷方式,则它可能无法在应该的时候执行其功能。

    下面是你可以尝试的:打开程序写一些东西。试着用 . 您将看到,即使应该发生,也不会发生任何事情,因为菜单项的状态没有更新。如果单击“菜单”,然后再次尝试使用快捷方式,文本缓冲区将被清除。

    我只是问一个为什么在按下快捷键时更新状态。我尝试了一些方法,建立在 Ctrl键 已按下(我无法仅检查 Ctrl+D键 ,我可能有另一个快捷方式在一个程序),但他们都失败或产生错误。你能看到的方式之一 here .

    2 回复  |  直到 6 年前
        1
  •  0
  •   theGtknerd    6 年前

    如果要根据textbuffer中是否有文本来更新menuitem敏感度,请连接到textbuffer changed或modified changed信号。因为我不擅长C,但通常使用Python:

    textbuffer.connect("changed", update_menuitem_sensitivity) 
    

    changed

    modified-changed

        2
  •  0
  •   Hanlon    6 年前

    终于找到了工作方法。

    #include <gtk/gtk.h>
    
    struct check_sensitivity
    {
            GtkWidget *menuitem;
            GtkTextBuffer *buffer;
    };
    
    void sensitivity(GtkWidget *menu, struct check_sensitivity *sens);
    
    void check_sensitivity_on_ctrl(GtkWidget *window, GdkEventKey *key, struct check_sensitivity *sens)
    {
        if(key->keyval == GDK_KEY_Control_L || key->keyval == GDK_KEY_Control_R)
        {
            sensitivity(NULL, sens);
        }
    }
    
    void sensitivity(GtkWidget *menu, struct check_sensitivity *sens)
    {
            if (gtk_text_buffer_get_modified(sens->buffer))
                    gtk_widget_set_sensitive(sens->menuitem, TRUE);
            else
                    gtk_widget_set_sensitive(sens->menuitem, FALSE);
    }
    
    void menuitem_click(GtkWidget *menuitem, GtkTextBuffer *buffer)
    {
            gtk_text_buffer_set_text(buffer, "", -1);
            gtk_text_buffer_set_modified(buffer, FALSE);
    }
    
    int main(int argc, char **argv)
    {
            gtk_init(&argc, &argv);
    
            struct check_sensitivity sens;
    
            GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_window_set_default_size(GTK_WINDOW(window), 400, 400);
            g_signal_connect(window, "delete-event", G_CALLBACK(gtk_main_quit), NULL);
    
            GtkWidget *view = gtk_text_view_new();
            sens.buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
        gtk_text_buffer_set_modified(sens.buffer, FALSE);
    
            GtkWidget *menubar = gtk_menu_bar_new();
            GtkWidget *menu = gtk_menu_new();
    
            GtkAccelGroup *shortcuts = gtk_accel_group_new();
            gtk_window_add_accel_group(GTK_WINDOW(window), shortcuts);
    
            GtkWidget *menuitem = gtk_menu_item_new_with_label("Menu");
            gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menu);
            gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menuitem);
            g_signal_connect(menuitem, "activate", G_CALLBACK(sensitivity), &sens);
            menuitem = gtk_menu_item_new_with_label("Clear");
            gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
            gtk_widget_add_accelerator(menuitem, "activate", shortcuts, GDK_KEY_D, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
            sens.menuitem = menuitem;
            g_signal_connect(sens.menuitem, "activate", G_CALLBACK(menuitem_click), sens.buffer);
        g_signal_connect_after(window, "key-press-event", G_CALLBACK(check_sensitivity_on_ctrl), &sens);
    
            GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
            gtk_box_pack_start(GTK_BOX(box), menubar, FALSE, FALSE, 0);
            gtk_box_pack_start(GTK_BOX(box), view, TRUE, TRUE, 0);
    
            gtk_container_add(GTK_CONTAINER(window), box);
    
            gtk_widget_show_all(window);
    
            gtk_main();
    }