Установить состояние пункта меню при быстром нажатии - PullRequest
0 голосов
/ 20 сентября 2018

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

Но с этим элементом меню также связан ярлык.Ярлык работает только при включенном пункте меню.

Как мы можем установить состояние пункта меню, не щелкая на меню, которое его удерживает, когда мы хотим использовать ярлык?

Вот пример программы, которая, надеюсь, сделает мой вопрос более понятным:

#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();
}

В этой программе состояние пункта меню «Очистить» зависит от того, был ли изменен буфер или нет.Разумеется, состояние устанавливается, когда пользователь нажимает на меню «Меню».

Существует также сочетание клавиш Ctrl + D , которое аналогично нажатию кнопки «Очистить».,Ярлык работает должным образом в зависимости от состояния пункта меню, но что неправильно, так это состояние пункта меню.Позвольте мне объяснить:

Поскольку пункт меню (не) установлен, когда пользователь нажимает «Меню», чтобы обновить состояние «Очистить» перед использованием ярлыка, пользователь должен щелкнуть по нему.Если ярлык используется перед обновлением состояния пункта меню, он может не выполнить свою функцию, когда это необходимо.

Вот что вы можете попробовать: открыть программу и написать что-нибудь.Попробуйте очистить его с помощью Ctrl + D .Вы увидите, что ничего не происходит, хотя это должно произойти, потому что состояние пункта меню не обновляется.Если вы нажмете «Меню», а затем попробуете снова использовать ярлык, текстовый буфер очистится.

Я просто спрашиваю, зачем обновлять состояние при нажатии ярлыка.Я пробовал несколько способов, которые основаны на установке состояния при нажатии Ctrl (я не могу проверить только для Ctrl + D , у меня могут быть другие ярлыки в программе), новсе они потерпели неудачу или создали ошибки.Одним из таких способов вы можете увидеть здесь .

Ответы [ 2 ]

0 голосов
/ 25 сентября 2018

Наконец-то нашел рабочий метод.

#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();
}
0 голосов
/ 20 сентября 2018

Если вы хотите обновить чувствительность пунктов меню в зависимости от того, есть ли текст в вашем текстовом буфере, подключитесь к сигналу измененного или измененного текстового буфера.Так как я не очень хорош в C, но обычно использую Python:

textbuffer.connect("changed", update_menuitem_sensitivity) 

изменено

изменено-изменено

...