c - 使创建的菜单的菜单项可使用 GTK+ 运行

标签 c menu gtk

在此代码中,我创建了一个菜单栏并向其中添加了菜单和菜单项... 但我不知道如何使创建的菜单项起作用...例如:我想要菜单栏中"file"的“打开”菜单项,打开一个文件并显示它... 我正在使用 GTK+ 3 在文本编辑器上制作一个项目

    #include <gtk/gtk.h>


    GtkWidget     *window;
    GdkPixbuf     *icon;
    GtkWidget     *vbox;

    GtkWidget     *menubar;
    GtkWidget     *fileMenu;
    GtkWidget     *fileMi;
    GtkWidget     *editMenu;
    GtkWidget     *editMi;
    GtkWidget     *searchMenu;
    GtkWidget     *searchMi;
    GtkWidget     *newMi;
    GtkWidget     *openMi;
    GtkWidget     *saveMi;
    GtkWidget     *saveasMi;
    GtkWidget     *quitMi;
    GtkWidget     *undoMi;
    GtkWidget     *redoMi;
    GtkWidget     *cutMi;
    GtkWidget     *copyMi;
    GtkWidget     *pasteMi;
    GtkWidget     *fontMi;
    GtkWidget     *findMi;
    GtkWidget     *replaceMi;
    GtkWidget     *text_view;
    GtkTextBuffer *buffer;

    void txt(){

    text_view = gtk_text_view_new ();
    gtk_box_pack_start (GTK_BOX (vbox), text_view, TRUE, TRUE, 0);


    }

    GdkPixbuf *create_pixbuf (const gchar *filename)
    {
    GdkPixbuf *pixbuf;
    GError    *error = NULL;

    pixbuf = gdk_pixbuf_new_from_file (filename, &error);

    if (!pixbuf)
    {
    fprintf (stderr, "%s\n", error->message);
    g_error_free (error);
    }

    return pixbuf;
    }

    static void fileOpen(GtkWidget *load, gpointer window)
    {
    GtkWidget *choose;
    GtkFileChooserAction action= GTK_FILE_CHOOSER_ACTION_OPEN;

    choose     =    gtk_file_chooser_dialog_new("Choose a file to open",  GTK_WINDOW(window), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_OK, GTK_RESPONSE_OK, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL);
    if (gtk_dialog_run(GTK_DIALOG(choose)) == GTK_RESPONSE_ACCEPT)
    {

    char *path     = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(choose));
    gtk_text_buffer_set_text(buffer, path, -1);
    }

    gtk_widget_destroy(choose);
    }

    static void fileSave(GtkWidget *save, gpointer window)
    {
    GtkWidget *saved;

    saved     =    gtk_file_chooser_dialog_new("Choose a file to open",  GTK_WINDOW(window), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_OK, GTK_RESPONSE_OK, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL);
    gtk_widget_show_all(saved);

    gint resp    =     gtk_dialog_run(GTK_DIALOG(saved));

    gtk_widget_destroy(saved);
    }


    int main (int argc, char *argv[])
    {


    gtk_init (&argc, &argv);

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    icon = create_pixbuf ("Web.png");

    gtk_window_set_title (GTK_WINDOW (window), "Write Pad");
    gtk_window_set_default_size (GTK_WINDOW (window), 500, 400);
    gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
    gtk_window_set_icon (GTK_WINDOW (window), icon);

    vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
    gtk_container_add (GTK_CONTAINER (window), vbox);

    menubar = gtk_menu_bar_new ();
    fileMenu = gtk_menu_new ();


    fileMi = gtk_menu_item_new_with_label ("File");
    newMi = gtk_menu_item_new_with_label ("New");
    openMi = gtk_menu_item_new_with_label ("Open");
    saveMi = gtk_menu_item_new_with_label ("Save");
    saveasMi = gtk_menu_item_new_with_label ("Save As");
    quitMi = gtk_menu_item_new_with_label ("Quit");

    menubar = gtk_menu_bar_new ();
    editMenu = gtk_menu_new ();

    editMi = gtk_menu_item_new_with_label ("Edit");
    undoMi = gtk_menu_item_new_with_label ("Undo");
    redoMi = gtk_menu_item_new_with_label ("Redo");
    cutMi = gtk_menu_item_new_with_label ("Cut");
    copyMi = gtk_menu_item_new_with_label ("Copy");
    pasteMi = gtk_menu_item_new_with_label ("Paste");
    fontMi = gtk_menu_item_new_with_label ("Font");

    menubar = gtk_menu_bar_new ();
    searchMenu = gtk_menu_new ();

    searchMi = gtk_menu_item_new_with_label ("Search");
    findMi = gtk_menu_item_new_with_label ("Find");
    replaceMi = gtk_menu_item_new_with_label ("Replace");

    gtk_menu_item_set_submenu (GTK_MENU_ITEM (fileMi), fileMenu);
    gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), newMi);
    gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), openMi);
    gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), saveMi);
    gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), saveasMi);
    gtk_menu_shell_append (GTK_MENU_SHELL (fileMenu), quitMi);
    gtk_menu_shell_append (GTK_MENU_SHELL (menubar), fileMi);

    gtk_menu_item_set_submenu (GTK_MENU_ITEM (editMi), editMenu);
    gtk_menu_shell_append(GTK_MENU_SHELL(editMenu), undoMi);
    gtk_menu_shell_append(GTK_MENU_SHELL(editMenu), redoMi);
    gtk_menu_shell_append(GTK_MENU_SHELL(editMenu), cutMi);
    gtk_menu_shell_append(GTK_MENU_SHELL(editMenu), copyMi);
    gtk_menu_shell_append (GTK_MENU_SHELL (editMenu), pasteMi);
    gtk_menu_shell_append (GTK_MENU_SHELL (editMenu), fontMi);
    gtk_menu_shell_append (GTK_MENU_SHELL (menubar), editMi);

    gtk_menu_item_set_submenu (GTK_MENU_ITEM (searchMi), searchMenu);
    gtk_menu_shell_append(GTK_MENU_SHELL(searchMenu), findMi);
    gtk_menu_shell_append(GTK_MENU_SHELL(searchMenu), replaceMi);

    gtk_box_pack_start (GTK_BOX (vbox), menubar, FALSE, FALSE, 0);
    txt();
    buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));

    g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (gtk_main_quit), NULL);
    g_signal_connect (G_OBJECT (quitMi), "activate", G_CALLBACK (gtk_main_quit), NULL);
    g_signal_connect (G_OBJECT (newMi), "activate", G_CALLBACK (main), NULL);
    g_signal_connect(G_OBJECT (openMi), "activate", G_CALLBACK(fileOpen), NULL);
    g_signal_connect(G_OBJECT (saveMi), "activate", G_CALLBACK(fileSave), NULL);

    gtk_widget_show_all (window);

    gtk_main ();

    return 0;
    }

最佳答案

基本上,您遇到的问题是由于所有小部件都是全局变量而引起的,但您的 fileOpen 函数采用 gpointer window 参数:

//global
GtkWidget *window;

//gpointer window argument -> local variable, not global
static void fileOpen(GtkWidget *load, gpointer window)
{
    GtkWidget *choose;
    GtkFileChooserAction action= GTK_FILE_CHOOSER_ACTION_OPEN;

    choose = gtk_file_chooser_dialog_new(
        "Choose a file to open",
        GTK_WINDOW(window),//window is not global, but function argument here !
        GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_OK, GTK_RESPONSE_OK, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL
    );
    if (gtk_dialog_run(GTK_DIALOG(choose)) == GTK_RESPONSE_ACCEPT)
    {
        char *path = gtk_file_chooser_get_filename(
            GTK_FILE_CHOOSER(choose)
        );
        gtk_text_buffer_set_text(buffer, path, -1);
    }
    gtk_widget_destroy(choose);
}

一个快速修复方法是将参数重命名为 gp_data 之类的名称。更好的解决方法是使用全局变量,而是依赖gpointer来传递您需要的对象:

g_signal_connect(
    G_OBJECT (openMi),
    "activate",
    G_CALLBACK(fileOpen),
    (gpointer)text_view // text_view and buffer needn't be global now
);

然后使用 gpointer 参数来获取窗口和您可能需要的任何其他内容。您还可以使用自定义 struct 或小部件数组来传递给回调,以防您需要更多内容来处理,但在这种情况下,您应该可以只传递 text_view 小部件,并且将回调更改为如下所示:

static void fileOpen(GtkWidget *load, gpointer widget)
{
    //get the buffer
    GtkTextBuffer *buffer = gtk_text_view_get_buffer(
        GTK_TEXT_VIEW (widget)
    );
    //get window from text_View widget passed to callback
    //so window doesn't have to be global either...
    GtkWidget *window = gtk_widget_get_toplevel(
        widget
    ), *choose;
    GtkFileChooserAction action= GTK_FILE_CHOOSER_ACTION_OPEN;

    choose = gtk_file_chooser_dialog_new(
        "Choose a file to open",
        GTK_WINDOW(window),
        GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_OK, GTK_RESPONSE_OK, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, NULL
    );
    if (gtk_dialog_run(GTK_DIALOG(choose)) == GTK_RESPONSE_ACCEPT)
    {
        char *path = gtk_file_chooser_get_filename(
            GTK_FILE_CHOOSER(choose)
        );
        gtk_text_buffer_set_text(buffer, path, -1);
    }
    gtk_widget_destroy(choose);
}

请注意,我尚未测试此代码,但这应该足以让您入门。您必须稍微更改一下代码,但是您应该能够简单地通过将正确的小部件传递给回调来摆脱所有这些全局变量。

一如既往:Read the documentation ,只需将链接添加到答案以供将来引用

关于c - 使创建的菜单的菜单项可使用 GTK+ 运行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37920726/

相关文章:

c++ - 识别字节序相关的问题

c - 通过偏移量访问结构

c - 填充结构的实际大小,(成员大小的总和,没有用于对齐的填充)

android - 选项菜单不会在 Android 4.1.1 中显示

ubuntu - 将字符串对象添加到 gArray

c++ - 如何在 VS Code 中编译 c/c++ 时禁用自动创建 exe 文件?

java - 如何不间断地显示我的导航栏内容?

c# - 在将文本粘贴到 TextView 之前捕获文本

c++ - 使用 MinGW 帮助在 Windows 上编译 GTK+

javascript - 如何从外部文件加载导航菜单? (没有 Wamp,所有代码必须是 'browser-side' )