【问题标题】:How do i organize a GTK program?如何组织 GTK 程序?
【发布时间】:2021-05-18 23:12:33
【问题描述】:

我有一个名为create_interface 的函数。在该函数中是打开菜单按钮的信号处理程序(菜单在create_interface 中创建)。我想传递窗口小部件并传递树视图小部件,因为当您打开文件时,树视图中的条目应该会显示出来。我尝试将它们作为结构传递,但是,虽然它可以工作,但 GTK 会生成一些错误消息。

// This is global.
struct everything
        {
                GtkWidget *window;
                GtkWidget *tree_view;
        }

GtkWidget *create_interface (void)
{
        struct everything instance;
        struct everything *widgets;
        widgets = &instance;
        
        ...code here...

        g_signal_connect(file_mi_open_file_dialog, "clicked", G_CALLBACK(open_file_dialog), widgets);

函数open_file_dialog 如下所示:

void open_file_dialog (GtkWidget *wid, gpointer data)
{
        struct everything *sample_name = data;
        ...rest of code here...

我想知道是否有另一种组织程序的方法,这样您就不必拥有全局变量。

【问题讨论】:

  • "GTK 生成一些错误信息。"你会和我们分享这条信息吗?

标签: c global-variables gtk organization code-organization


【解决方案1】:

我尝试将它们作为结构传递,但是,虽然它可以工作,但 GTK 会生成一些错误消息。

问题在于您正在尝试使用堆栈分配的结构,该结构在 create_interface() 函数完成后变得无效,而您通常希望这些值在稍后的时刻仍然有效(例如例如,当open_file_dialog() 被调用时。

我想知道是否有另一种组织程序的方法,这样您就不必拥有全局变量。

一个可能的解决方案确实是使用全局变量:这将在程序的整个生命周期内有效,但它有很大的缺点:如果你必须为每个回调都这样做,它就无法扩展,而且它在架构上不是真的很干净。

另一种解决方案是在堆上分配“闭包”(即在创建回调时要捕获的变量),并在完成后释放它。 GLib 甚至可以通过调用 g_signal_connect_data()(或 g_signal_connect_object(),如果您将字段保存在 GObject 中)来帮助您

// Technically you don't need the typedef
typedef struct _ClickedClosure {
    GtkWidget *window;
    GtkWidget *treeview;
} ClickedClosure;

GtkWidget *create_interface (void)
{
    // Note that the g_new0 allocates on the heap instead of using the stack
    ClickedClosure *closure = g_new0 (ClickedClosure, 1);

    // code here to initialize your window/treeview ...

    // put the widgets in the closure
    closure->window = my_window;
    closure->treeview = treeview;

    // Connect to the signal
    g_signal_connect_data(file_mi_open_file_dialog, "clicked",
                          G_CALLBACK(open_file_dialog), closure, g_free, 0);
}

void open_file_dialog (GtkWidget *wid, gpointer data)
{
    // Since this was allocated on the heap, this is still valid
    ClickedClosure *sample_name = data;

    // code handling here ...
}

通常,使用 GTK 的开发人员所做的是,他们已经在使用自己的 GObject 类/对象,然后他们可以使用 g_signal_connect_object(),或者稍后使用 g_object_unref() 手动释放它。然后使用 GObject 还允许您进行运行时类型检查强制转换,以确保您的闭包具有正确的类型。

【讨论】:

    猜你喜欢
    • 2010-11-18
    • 2011-05-19
    • 1970-01-01
    • 1970-01-01
    • 2011-02-12
    • 2012-08-09
    • 2018-11-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多