【问题标题】:GTK+3 file chooser in a non-GTK application非 GTK 应用程序中的 GTK+3 文件选择器
【发布时间】:2015-06-10 08:35:41
【问题描述】:

我有一个完全不使用 GTK 的 C 项目(在 Linux 上),但我只想将 GTK 用于某些特定任务,例如选择文件(文件选择器对话框)。所以我没有 GTK 父窗口,没有 gtk 主循环等,我只想要一个文件选择器对话框,它应该阻止我的程序的执行,直到用户选择一个文件(或取消),然后我不使用 GTK曾经。我试过的:

https://developer.gnome.org/gtk3/stable/GtkFileChooserDialog.html

我使用了“典型用法”中的代码,第一个示例。我将 gtk_init(&argc, &argv) 放在程序的开头,当我需要文件选择器时,我使用该示例中的代码调用一个函数(我使用 parent 作为 NULL,因为没有父级)。结果是一个闪烁的窗口几分之一秒,然后是 SIGSEGV。在此之前,我有此消息:

Gtk-Message: GtkDialog mapped without a transient parent. This is discouraged.

我已经在 stackoverflow 上阅读了有关此消息的问题/答案,但崩溃应用程序对我来说是更严重的事情。我也试过这样说:

gtk_widget_show_all(dialog);

在没有导致崩溃的 gtk_file_chooser_dialog_new() 之后,我可以选择文件,但随后我在 gtk_file_chooser_get_filename() 周围再次获得了 SIGSEGV。

在使用 gdb 时,我得到了这个:

Program received signal SIGSEGV, Segmentation fault.
__GI___pthread_mutex_lock (mutex=0x3c3) at ../nptl/pthread_mutex_lock.c:67

你能帮我看看我犯了什么错误吗?我对 GTK 编程不太熟悉,所以我尝试使用手册中的示例,但似乎不起作用。提前非常感谢!

【问题讨论】:

    标签: c gtk3 filechooser


    【解决方案1】:

    你不能使用没有 gtk 主循环的小部件。

    好吧,看来我错了。我真诚的道歉!我实际上尝试过这样做,而结论正是我所描述的。但是最近几天这个问题一直困扰着我,所以我做了一些更多的挖掘和实验,并提出了以下程序:

    /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 8 -*-  */
    /*
     * main.c
     * Copyright (C) 2015 John Coppens <john@jcoppens.com>
     * 
     * standalone_filechooser is free software: you can redistribute it and/or modify it
     * under the terms of the GNU General Public License as published by the
     * Free Software Foundation, either version 3 of the License, or
     * (at your option) any later version.
     * 
     * standalone_filechooser is distributed in the hope that it will be useful, but
     * WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     * See the GNU General Public License for more details.
     * 
     * You should have received a copy of the GNU General Public License along
     * with this program.  If not, see <http://www.gnu.org/licenses/>.
     */
    
    #include <stdio.h>
    #include <gtk/gtk.h>
    
    GtkWidget *
    create_filechooser_dialog(char *init_path, GtkFileChooserAction action)
    {
      GtkWidget *wdg = NULL;
    
      switch (action) {
        case GTK_FILE_CHOOSER_ACTION_SAVE:
          wdg = gtk_file_chooser_dialog_new("Save file", NULL, action,
            "Cancel", GTK_RESPONSE_CANCEL,
            "Save", GTK_RESPONSE_OK,
            NULL);
          break;
    
        case GTK_FILE_CHOOSER_ACTION_OPEN:
          wdg = gtk_file_chooser_dialog_new("Open file", NULL, action,
            "Cancel", GTK_RESPONSE_CANCEL,
            "Open", GTK_RESPONSE_OK,
            NULL);
          break;
    
        case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
        case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER:
          break;
      }
    
      return wdg;
    }
    
    int main(int argc, char *argv[])
    {
      GtkWidget *wdg;
      char *fname = "";
    
      if (argc == 2)
        fname = argv[1];
    
      gtk_init(&argc, &argv);
    
      wdg = create_filechooser_dialog(fname, GTK_FILE_CHOOSER_ACTION_OPEN);
      if (gtk_dialog_run(GTK_DIALOG(wdg)) == GTK_RESPONSE_OK) {
        printf("%s", gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(wdg)));
        return(0);
      } else  
        return (1);
    }
    

    您可以从另一个程序(甚至终端)调用对话框

    standalone_filechooser [default file]
    

    如果提供了default file(没有括号),它将被选中。如果选择了一个文件,它将打印在stdout,否则程序将返回error=1

    在没有主窗口的情况下运行小部件仍然存在一个小问题,这会导致将消息发送到stderr:GtkDialog mapped without a transient parent. This is discouraged。我认为这确实是一个错误(在更新的 gtk3 版本中是 it might be solved)。由于消息是发送到stderr,所以应该不会影响正常使用。

    【讨论】:

    • 或者,作为使用 GTK 的替代方案,您可能需要考虑将 zenity 作为子进程运行。
    • 我也这么认为(使用 gtk 主循环),但 gtk_dialog_run() 感觉可以解决问题。另请注意,仅在我提到的示例中,仅显示了几分之一秒的窗口。但是我觉得这是某种链接问题,因为我也使用 SDL,并且 sdl2-config --cflags / --libs 使用 -D_REENTRANT 而 gtk 似乎想要为 gcc 切换 -pthread ,因为 gdb 报告在nptl/thread 的东西,我只是想这里有一些冲突?但是好的,我会尝试你的想法,无论如何它看起来更完美的解决方案,我会看到,如果它是好的,告诉+接受!谢谢!
    • @duskwuff 好主意,部分:我会检查 zenity 的来源 :-) 也许它有助于创建一个简单的文件选择器,正确的方式 (TM)。 :) 如果可能的话,我不想过多地使用外部程序......
    • 如果您需要在对话框关闭后运行代码,这不起作用。由于主循环没有运行,它永远不会关闭对话框,它只是冻结。该示例之所以有效,是因为程序立即结束。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多