2015-06-10 3 views
0

У меня есть проект C (в Linux), который вообще не использует GTK, но я хотел бы использовать GTK только для некоторых конкретных задач, таких как выбор файла (выбор файла диалог). Поэтому у меня нет родительского окна GTK, нет основного цикла gtk и т. Д. Мне нужен диалог выбора файлов, который должен блокировать выполнение моей программы до того, как пользователь выберет файл (или отменен), и я не буду использовать GTK после этого Когда-либо. То, что я пробовал:Выбор файла GTK + 3 в приложении без 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(), который не приводит к аварии, я могу выбрать файл, но у меня есть SIGSEGV снова вокруг gtk_file_chooser_get_filename().

При использовании GDB, я получил это:

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

Можете ли вы помочь мне, что ошибка, которую я сделал? Я слишком плохо знаком с программированием GTK, поэтому я попытался использовать примеры из руководства, но он, похоже, не работает. Заранее большое спасибо!

ответ

1

Вы не можете использовать виджеты без gtk mainloop.

Ну, кажется, я был неправ. Мои искренние извинения! I имел на самом деле пытался сделать это раньше, и выводы были именно тем, что я описал. Но этот вопрос меня прослушивают за последние дни, так что я еще немного копать и экспериментировать и придумал следующую программу:

/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 8 -*- */ 
/* 
* main.c 
* Copyright (C) 2015 John Coppens <[email protected]> 
* 
* 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, иначе программа вернется с ошибкой = 1

Есть еще небольшая проблема с запуском виджета без главного окна, что приводит к отправке сообщения на stderr: GtkDialog mapped without a transient parent. This is discouraged. Я думаю, что это действительно ошибка (и it might be solved в более поздней версии gtk3). Поскольку сообщение отправляется в stderr, оно не должно мешать нормальному использованию.

+0

Или, как альтернатива использованию GTK вообще, вы можете захотеть запустить ['zenity'] (https://help.gnome.org/users/zenity/stable/file-selection.html.en) как подпроцесс. – duskwuff

+0

Я тоже так думал (с основной петлей gtk), но gtk_dialog_run() чувствовал, что это трюк. Также обратите внимание на то, что только в примере, о котором я упоминал, окно отображается всего лишь на долю секунды.Однако у меня такое ощущение, что это какая-то проблема связывания, поскольку я тоже использую SDL, а sdl2-config --cflags/-libs использует -D_REENTRANT, в то время как gtk, похоже, хочет -pthread-переключатель для gcc, так как сообщения gdb вылетают из nptl/thread stuff, я просто думаю о каком-то конфликте здесь? Но, хорошо, я попробую вашу идею, все равно выглядит более полированным решением, я посмотрю, и скажите +, согласитесь, было ли это oK! БЛАГОДАРЯ! – LGB

+0

@ duskwuff Хорошая идея, отчасти: я проверю источник зенитности :-) Может быть, это помогает создать простой файлообменник, правильный путь (TM). :) Я бы не хотел слишком много использовать внешние программы, если это возможно ... – LGB

Смежные вопросы