【问题标题】:I would like some help getting criteria of gtk programming. What could I do about this?我想要一些帮助来获得 gtk 编程的标准。我能做些什么呢?
【发布时间】:2014-07-23 22:01:22
【问题描述】:

谁能帮帮我?我有 C 编程技能,我正在尝试使用 gtk 对 gui 进行编程。我希望,通过从小部件(例如按钮)触发动作(回调函数),我可以更改属于任何其他小部件的任何条件或特征。即,允许从回调函数中完全可见,就好像所有 gui 小部件(例如单个主应用程序窗口)中的所有变量都是全局的。我怎样才能找到最接近的方法来实现这一点?到目前为止,当我尝试制作比简单的 Hello World 教程更复杂的东西时,我尝试发现使用 gtk 编程的基本概念的步骤让我感到沮丧。我还尝试使用:

/* out of main */
struct data_widgets
{
struct data_widgets * myp;
gchar  **loc ;      // LOCAL name
gchar  **rem ;      // REMOTE name
gchar  **pmte ;     // Plain message to encrypt filename
gchar  **lem ;      // Local encrypted message filename 
gchar  **emr ;      // Encrypted message received filename 
gchar  **pmr ;      // Plain message received filename 
gchar  **lopk ;     // Local owner public key filename 
gchar  **crpk ;     // Current remote public key filename  
};

int main(int argc, char *argv[])
{
gchar loc_str[100] = "*";       /* LOCAL name for filechoose filter */
gchar rem_str[100] = "*";       /* REMOTE name idem */
gchar pmte_str[100]= "plainmsgtoencrypt"; /* Plain message to encrypt filename  */
gchar lem_str[100] = "localencmsg"; /* Local encrypted message filename  */
gchar emr_str[100] = "encmsgreceiv"; /* Encrypted message received filename */
gchar pmr_str[100] = "plainreceiv"; /* Plain message received filename */
gchar lopk_str[100]= "locownpubkey"; /* Local owner public key filename */
gchar crpk_str[100]= "remotpubkey"; /* Current remote public key filename */

struct data_widgets mydata;

mydata.loc = &loc_str;
mydata.rem = &rem_str;
mydata.pmte = &pmte_str;
mydata.lem = &lem_str;
mydata.emr = &emr_str;
mydata.pmr = &pmr_str;
mydata.lopk = &lopk_str;
mydata.crpk = &crpk_str;
mydata.myp = &mydata;
/* in main */
....
/* in my callback */
struct data_widgets *pp = (struct data_widgets *) data;

/*passing gpointer data as &mydata.myp, and doing (*pp)->(any pointer) this try fail*/

【问题讨论】:

  • 我想重新表述我的帮助请求,不是在请求文献的意义上,而是执行我在段落中间提到的编程尝试,阐述修改参数小部件的广泛可见性回调函数。谢谢。
  • 我不知道它有多清晰,但现在它更切题了。我将撤回我的近距离投票。感谢您的编辑。 :-)

标签: c gtk


【解决方案1】:

据我了解,您希望从回调中访问小部件,而不必携带一堆全局变量。你有一些选择。

您可以将数据和小部件打包到单个结构中,并将其作为user_data 传递给回调。

struct snapshot {
    struct data_widgets data;
    GtkWidget *entry;
    GtkWidget *box;
    GtkWidget *label;
    GtkWidget *whatever;
};
/* Now fill and use the above struct as user_data */

GtkWidget 字段应在您用于创建 UI 内容的代码中进行初始化。

您还可以使用gtk_widget_set_name() 为每个相关小部件设置名称(Glade 自动为每个元素设置名称)。一旦您需要一个小部件,只需通过gtk_widget_get_name() 获取它。

static void a_callback(GtkWidget *widget, gpointer user_data)
    GtkWidget *an_entry = NULL;
    GtkWidget *toplevel = gtk_widget_get_toplevel(widget);
    if (gtk_widget_is_toplevel(toplevel))
        an_entry = gtk_widget_get_name(toplevel, "name of the entry");
    g_return_if_fail(an_entry != NULL);
    /* ... do something with an_entry ... */
}

您还可以像 DOM 一样遍历小部件层次结构,或使用 g_object_set_data() 或上述任何有效组合将数据直接绑定到小部件。

附录

使用g_object_set_data(),您可以将任意数据附加到任何GObject 实例,例如:

gchar *text;

/* Bind some data to widget */
g_object_set_data(G_OBJECT(widget), "pmte", "plainmsgtoencrypt");
g_object_set_data(G_OBJECT(widget), "lem", "localencmsg");

text = g_object_get_data(G_OBJECT(widget), "pmte");
g_print("%s\n", text); /* Print "plainmsgtoencrypt" */
g_free(text);

text = g_object_get_data(G_OBJECT(widget), "lme");
g_print("%s\n", text); /* Print "localencmsg" */
g_free(text);

代码清理

你的代码在很多方面都很混乱:我建议你忘记你从 C 中学到的东西,然后从零开始。你的数据比它需要的多一级间接,myp 是假的,你正在指定数组的大小并初始化它。

回答您的评论:以下代码是自包含的,不会抛出您看到的错误。

#include <gtk/gtk.h>

struct data_widgets {
    gchar **crpk;
};

void callback(GtkWidget *widget, gpointer user_data) {
    struct data_widgets *data = user_data;
    g_print("%s\n", data->crpk); /* Prints remotpubkey */
}

int main(int argc, char *argv[]) {
    gchar crpk_str[100] = "remotpubkey";
    struct data_widgets mydata;

    mydata.crpk = &crpk_str;

    callback(NULL, &mydata);
    return 0;
}

相同的代码,以理智的方式清理:

#include <gtk/gtk.h>

typedef struct {
    gchar *crpk;
} data_t;

void callback(GtkWidget *widget, gpointer user_data) {
    data_t *data = user_data;
    g_print("%s\n", data->crpk); /* Prints remotpubkey */
}

int main() {
    data_t mydata;

    mydata.crpk = "remotpubkey";

    callback(NULL, &mydata);
    return 0;
}

【讨论】:

  • myp 是一个指向结构体的指针,在结构体内部传递。主要概念是不要以某种方式生成全局变量以达到代码的可移植性。我会尝试应用他的建议,努力推进我所尝试的。测试后我会公布结果。当然,非常感谢您的宝贵贡献。关于你的最后一段(g_objet_set_data),我不知道如何使用它,我可以在网上找到的教程不包括这样的复杂程度。
  • 我还是不明白:可以访问myp 意味着您已经拥有指向同一个结构的指针。两种情况:或者你的 C 语言有严重问题,或者我完全看不懂你的代码。
  • 我还是添加了一个使用 g_object_{get,set}_data 的示例。
  • 在我的代码中,我传递了(gpointer data)——一个指向void的指针——作为&mydata.myp,它是一个用我的data_widgets结构的地址初始化的指针。在我的回调中,我制作了一个强制转换 data_widgets struct * pp = (struct data_widgets *) 数据,这应该允许我毫无问题地对函数进行引用 (*pp)->(any_struct_member)。 data_struct 结构是在 main 之外声明的,因此它的指针算法在函数内部也应该是可见的。但我收到一个错误:eccelgam-jvr05.c.20:30: error: dereference pointer to compatible type.
  • 如果您直接传递&amp;mydata,您将获得完全相同的结果,而无需添加其他字段和代码。
猜你喜欢
  • 1970-01-01
  • 2016-02-18
  • 1970-01-01
  • 2018-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-21
  • 2014-12-23
相关资源
最近更新 更多