c - 使用 GtkFileChooserButton 和 GtkFileChooserDialog 的区别
问题描述
我想让用户选择两个目录,然后在单击按钮后检索他们的 URI,这样我就可以将它们传递给另一个函数。现在我试图做一些事情:
directory1 = gtk_file_chooser_button_new ("Choose directory 1",GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
目录 2 也是如此。然后将它们放入结构中
struct directories {
GtkWidget *first;
GtkWidget *second;
};
struct directories directory;
directory.first = directory1;
directory.second = directory2;
单击按钮后,将其传递给当前什么都不做但尝试检索 URI 并打印它们的函数。
g_signal_connect(button, "clicked", G_CALLBACK(print_test), &directory);
print_test (struct directories *dirc)
{
g_print("%s\n", gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(dirc->first)));
g_print("%s\n", gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(dirc->second)));
}
我也尝试过替换GTK_FILE_CHOOSER
,GTK_FILE_CHOOSER_BUTTON
但结果是一样的:我的程序已编译,我选择了一些目录,在激活按钮后它崩溃并打印了一个
(无效的)
以及以下调试信息
GLib-GObject-WARNING **: 02:52:03.786: invalid uninstantiatable type 'gchararray' in cast to 'GtkFileChooserButton'
Gtk-CRITICAL **: 02:52:03.786: gtk_file_chooser_get_uri: assertion 'GTK_IS_FILE_CHOOSER (chooser)' failed
我认为 gtk_file_chooser_button 是一个很好的解决方案,因为它似乎比手动建立对话框更简单,但现在我开始质疑是否允许我以这种方式使用它,或者我的程序失败是错误的传递指针方法的错误打印测试。不幸的是,我发现的所有示例都集中在使用对话框上,所以我没有找到一个可以学习如何使用 gtk_file_chooser_button 的好示例。
编辑:根据要求,我展示我的代码示例。我只删除了与此问题无关的其他类型的按钮,并执行了第一条评论中描述的更改,因此与上述问题相比,您可以观察到两行的细微差别。
#include <stdio.h>
#include <gtk/gtk.h>
struct directories {
GtkWidget *first;
GtkWidget *second;
};
static void
print_test (GtkWidget *somewidget, struct directories *dirc)
{
g_print("%s\n", gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(dirc->first)));
g_print("%s\n", gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(dirc->second)));
}
static void
set_expand (GtkWidget *widget)
{
gtk_widget_set_hexpand(widget, 1);
gtk_widget_set_vexpand(widget, 1);
}
static void
activate (GtkApplication* app,
gpointer user_data)
{
GtkWidget *window;
GtkWidget *grid;
GtkWidget *frame;
GtkWidget *settings;
GtkWidget *directory1;
GtkWidget *directory2;
GtkWidget *button;
//Prepare the window
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Sagger");
gtk_window_set_default_size (GTK_WINDOW (window), 400, 200);
gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);
//Prepare the grid
grid = gtk_grid_new();
//gtk_grid_set_column_homogeneous(grid, 1);
//gtk_widget_set_halign (grid, GTK_ALIGN_FILL);
//gtk_widget_set_valign (grid, GTK_ALIGN_FILL);
set_expand(grid);
gtk_container_add(GTK_CONTAINER(window), grid);
//Prepare directory chooser
settings = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
frame = gtk_frame_new("Choose directories");
set_expand(settings);
gtk_container_add(GTK_CONTAINER(frame), settings);
directory1 = gtk_file_chooser_button_new ("Source directory",GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
set_expand(directory1);
gtk_container_add(GTK_CONTAINER(settings), directory1);
directory2 = gtk_file_chooser_button_new ("Target directory",GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
set_expand(directory2);
gtk_container_add(GTK_CONTAINER(settings), directory2);
gtk_grid_attach(grid, frame, 0, 0, 2, 1);
//Prepare the run button
settings = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
gtk_button_box_set_layout(GTK_BUTTON_BOX(settings), GTK_BUTTONBOX_EXPAND);
set_expand(settings);
gtk_grid_attach(grid, settings, 0, 2, 2, 1);
button = gtk_button_new_with_label("RUN");
//Try to pass the chosen directories
struct directories directory;
directory.first = directory1;
directory.second = directory2;
g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(print_test), (gpointer) &directory);
gtk_container_add(GTK_CONTAINER(settings), button);
gtk_widget_show_all (window);
}
int
main (int argc,
char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("pl.etua.sagger", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}
解决方案
directory
是函数的本地activate()
函数,并且如评论中所述,当它超出范围时将被销毁。稍后,当print_test()
单击按钮时调用该函数时,它会尝试访问该内存,从而导致分段错误。
两个简单的方法:
使directory
全局:
struct directories {
GtkWidget *first;
GtkWidget *second;
};
struct directories directory;
或使其成为静态activate()
:
static struct directories directory;
推荐阅读
- performance - 是使用规范工作负载所花费的总时间作为基准还是计算单个操作所花费的周期/时间?
- apiconnect - 如何使用 API Connect Test and Monitor 创建集成测试?
- angular - Angular-piwik ngp-set-site-id
- java - 在 gradle 的 jar 命令中使用 include 和 exclude 并不包括所有需要的类
- visual-studio-code - 为什么我从 VS Code 对 Rust 程序所做的更改在编译时没有反映出来?
- database - COUNT、IIF 用于计算也匹配特定字段值的记录
- arrays - 在两个数组中查找匹配
- azure - 如何从 ADF 执行本地 python 脚本
- android - 我无法连接到 firebase 只有这一行实现 'com.google.firebase:firebase-core:16.0.0:15.0.0'
- jenkins - 将 Jenkins 节点标记为在外部使用