如何刷新,在gtk中重画一个窗口(widget)? [英] How to refresh, redraw a window (widget) in gtk?

查看:1036
本文介绍了如何刷新,在gtk中重画一个窗口(widget)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Opensuse 13.1 Linux Os。我是gtk2和c的新手。我正在尝试创建一个应用程序,它可以在按照用户键入的值附加的表上放置一个按钮。我的程序代码如下所示:<$ p
$ b

  #include< stdlib.h> 
#include< gtk / gtk.h>

typedef struct {
GtkWidget * value1,* value2,* value3,* value4;
} entrygrouped;

guint ival1,ival2,ival3,ival4;

void button_clicked(entrygrouped * widget)
{
const gchar * value1,* value2,* value3,* value4;

value1 = gtk_entry_get_text(GTK_ENTRY(widget-> value1));
value2 = gtk_entry_get_text(GTK_ENTRY(widget-> value2));
value3 = gtk_entry_get_text(GTK_ENTRY(widget-> value3));
value4 = gtk_entry_get_text(GTK_ENTRY(widget-> value4));

ival1 =(guint)atoi(value1);
ival2 =(guint)atoi(value2);
ival3 =(guint)atoi(value3);
ival4 =(guint)atoi(value4);

g_print(ENTRY VALUES =%s%s%s%s\\\
,value1,value2,value3,value4);
g_print(ENTRY NUMS =%d%d%d%d \ n,ival1,ival2,ival3,ival4);

$ b $ int main(int argc,char * args [])
{
GtkWidget * window,* vbox,* uptable,* downtable,* label;
GtkWidget *按钮,* button2;
gtk_init(& argc,& args);

window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_get_resizable(GTK_WINDOW(window));

入门* eg;
eg = g_slice_new(entrygrouped);

vbox = gtk_vbox_new(FALSE,2);
uptable = gtk_table_new(3,4,FALSE);
downtable = gtk_table_new(3,3,TRUE);

label = gtk_label_new(输入值来定位小部件);
eg-> value1 = gtk_entry_new();
eg-> value2 = gtk_entry_new();
eg-> value3 = gtk_entry_new();
eg-> value4 = gtk_entry_new();
button = gtk_button_new_with_label(提交);
button2 = gtk_button_new_with_label(BUTTON);

gtk_table_attach_defaults(GTK_TABLE(uptable),label,0,3,0,1);
gtk_table_attach_defaults(GTK_TABLE(uptable),eg-> value1,0,1,1,2);
gtk_table_attach_defaults(GTK_TABLE(uptable),eg-> value2,1,2,1,2);
gtk_table_attach_defaults(GTK_TABLE(uptable),eg-> value3,0,1,2,3);
gtk_table_attach_defaults(GTK_TABLE(uptable),eg-> value4,1,2,2,3);
gtk_table_attach_defaults(GTK_TABLE(uptable),button,1,2,3,4);

gtk_widget_queue_draw(GTK_WIDGET(window));

gtk_table_attach_defaults(GTK_TABLE(downtable),button2,ival1,ival2,
ival3,ival4);

gtk_box_pack_start(GTK_BOX(vbox),uptable,0,0,0);
gtk_box_pack_start(GTK_BOX(vbox),downtable,0,0,0);


g_signal_connect_swapped(G_OBJECT(button),clicked,
G_CALLBACK(button_clicked),例如);

g_signal_connect_swapped(G_OBJECT(window),destroy,
G_CALLBACK(gtk_main_quit),NULL);

gtk_container_add(GTK_CONTAINER(window),vbox);
gtk_widget_show_all(window);

gtk_main();
返回0;

$ / code>

现在每当我从终端打开我的应用程序并输入一些值并点击提交按钮,值被打印在终端,但问题是窗口没有绘制新的赋值button2。我不知道任何可以刷新或重新绘制整个窗口的函数,尽管我试过了

  while (gtk_events_pending())
gtk_main_iteration();

上面的button2表附件仍然是我的窗户什么都不做。
我是否需要另一个回调函数来调整窗口大小?请帮我解决这个问题。



编辑:
如果我的问题不清楚,我想以图形化方式显示如下

--------------------------- -
| a.out _ [] x |
----------------------------在进入
|之前-------------------------- |值
|| | ||
| -------------------------- |
|| | ||
| -------------------------- |
| ________ |
| |提交||
| -------- |
----------------------------

---------- ------------------
| a.out _ [] x |
----------------------------输入
|后-------------------------- |值
|| 0 | 1 ||
| -------------------------- | button2小部件应该是
|| 0 | 1 ||根据
|重新绘制-------------------------- |输入的值和窗口
| ________ |小部件应该更新
| |提交||
| -------- |
| _________ |
| | Button | |
| --------- |
----------------------------


解决方案

经过大量阅读和挫折后,我终于能够解决我的问题了,我的应用程序的目的是了解表格附件的工作原理。


  1. 因此,我为问题做了简单的解决方案。将新按钮附加到对话框中,在clicked事件之后调用,回调如下



  static void fundia(GtkButton * button,GtkWindow * parent)
{
GtkWidget * dialog,* table,* button2;
dialog = gtk_dialog_new_with_buttons(Information,parent,
GTK_DIALOG_MODAL,GTK_STOCK_OK,GTK_RESPONSE_OK,
NULL);
button2 = gtk_button_new_with_label(BUTTON);

table = gtk_table_new(3,3,TRUE);
gtk_table_attach_defaults(GTK_TABLE(table),button2,ival1,ival2,
ival3,ival4);
gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(dialog) - > vbox),table);
gtk_widget_show_all(dialog);

gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog); $(

main()中的回调函数语句是



g_signal_connect(G_OBJECT(button),clicked,G_CALLBACK(fundia),(gpointer)window);



尽管这个函数符合我的目的,但上面的解决方案与这个贴子的问题无关,因此它没有重用或重绘这个窗口小部件。


  1. 因此,这里是我的程序的最终代码如下



  #include< stdlib.h> 
#include< gtk / gtk.h>
gboolean buttonbool = FALSE;

typedef struct {
GtkWidget * value1,* value2,* value3,* value4;
} entrygrouped;

static GtkWidget * button2 = 0;

guint ival1,ival2,ival3,ival4;

void button_clicked(gpointer data,entrygrouped * widget)
{
const gchar * cvalue1,* cvalue2,* cvalue3,* cvalue4;
cvalue1 = gtk_entry_get_text(GTK_ENTRY(widget-> value1));
cvalue2 = gtk_entry_get_text(GTK_ENTRY(widget-> value2));
cvalue3 = gtk_entry_get_text(GTK_ENTRY(widget-> value3));
cvalue4 = gtk_entry_get_text(GTK_ENTRY(widget-> value4));

ival1 =(guint)atoi(cvalue1);
ival2 =(guint)atoi(cvalue2);
ival3 =(guint)atoi(cvalue3);
ival4 =(guint)atoi(cvalue4);

g_print(ENTRY VALUES =%s%s%s%s\\\
,cvalue1,cvalue2,cvalue3,cvalue4);
g_print(ENTRY NUMS =%d%d%d%d \ n,ival1,ival2,ival3,ival4);

$ b $ showid(gpointer data,GtkWidget * widget)
{
if(buttonbool == TRUE)
{
/ *这里widget的引用计数减少1. * /
gtk_container_remove(GTK_CONTAINER(widget),GTK_WIDGET(button2));

/ *在下面的语句引用计数的小工具增加1 * /
g_object_ref(button2);
button2 = gtk_button_new_with_label(BUTTON);

gtk_table_attach_defaults(GTK_TABLE(widget),button2,ival1,ival2,
ival3,ival4);
} else {
gtk_table_attach_defaults(GTK_TABLE(widget),button2,ival1,ival2,
ival3,ival4);
buttonbool = TRUE;
}

gtk_widget_show(button2);

$ b $ int main(int argc,char * args [])
{
GtkWidget * window,* uptable,* downtable,* button,* vbox, * INSTR;

gtk_init(& argc,& args);

window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);
gtk_window_set_title(GTK_WINDOW(window),TABLEAPP);

入门* eg;
eg = g_slice_new(entrygrouped);

instr = gtk_label_new(输入值来定位小部件);
uptable = gtk_table_new(2,4,FALSE);
downtable = gtk_table_new(3,3,TRUE);
button = gtk_button_new_with_label(提交); //带标签的按钮
button2 = gtk_button_new_with_label(SAME);
//带标签的按钮
vbox = gtk_vbox_new(FALSE,2); // GTK vbox

eg-> value1 = gtk_entry_new();
eg-> value2 = gtk_entry_new();
eg-> value3 = gtk_entry_new();
eg-> value4 = gtk_entry_new();

gtk_table_attach_defaults(GTK_TABLE(uptable),instr,0,3,0,1);
gtk_table_attach_defaults(GTK_TABLE(uptable),eg-> value1,0,1,1,2);
gtk_table_attach_defaults(GTK_TABLE(uptable),eg-> value2,1,2,1,2);
gtk_table_attach_defaults(GTK_TABLE(uptable),eg-> value3,0,1,2,3);
gtk_table_attach_defaults(GTK_TABLE(uptable),eg-> value4,1,2,2,3);
gtk_table_attach_defaults(GTK_TABLE(uptable),button,1,2,3,4);

/ *第二个参数gtk_box_pack_start();是关于
小部件的扩展属性,它被设置为0,第三个关于分配填充属性也是
在我之前的程序中设置为0。 * /
gtk_box_pack_start(GTK_BOX(vbox),uptable,TRUE,TRUE,0);
gtk_box_pack_start(GTK_BOX(vbox),downtable,TRUE,TRUE,0);
$ b $ g_signal_connect(G_OBJECT(button),clicked,
G_CALLBACK(button_clicked),例如);

g_signal_connect(G_OBJECT(button),clicked,
G_CALLBACK(showid),downtable);

g_signal_connect_swapped(G_OBJECT(window),destroy,
G_CALLBACK(gtk_main_quit),NULL);

gtk_container_add(GTK_CONTAINER(window),vbox);

gtk_widget_show_all(window);

gtk_main();
返回0;

所以我做了以下区别: -


  1. 第二个和第三个参数的 gtk_box_pack_start(); 函数与扩展和填充属性在我之前的程序中被设置为0,这意味着我没有为它分配任何额外的空间。

  2. button2仅适用于main()。因此,我宣布main()函数可以被所有函数访问。
  3. 在将button2附加到可折叠的小部件后,当下一次我试图将button2重新附加到它所给予的表gtk_table_attach断言child-> parent == NULL失败错误。因此,前面的引用需要是免费的,因此在showid回调函数中添加了函数 gtk_container_remove(),以便将引用计数减少1.我再次引用 g_object_ref 将参考计数器增加1以再次引用小部件。

我想感谢Basile和Michi的帮助,它对我很有帮助。


I am using Opensuse 13.1 Linux Os. I am new to gtk2 and c. I am trying to create a application that can place a button on a table which is attached as per the values typed by the user. My program code is as following

#include <stdlib.h>
#include <gtk/gtk.h>

typedef struct {
    GtkWidget *value1, *value2, *value3, *value4;
} entrygrouped;

guint ival1, ival2, ival3, ival4;

void button_clicked(entrygrouped *widget)
{
    const gchar *value1, *value2, *value3, *value4;

    value1 = gtk_entry_get_text (GTK_ENTRY(widget->value1));
    value2 = gtk_entry_get_text (GTK_ENTRY(widget->value2));
    value3 = gtk_entry_get_text (GTK_ENTRY(widget->value3));
    value4 = gtk_entry_get_text (GTK_ENTRY(widget->value4));

    ival1 = (guint)atoi(value1);
    ival2 = (guint)atoi(value2);
    ival3 = (guint)atoi(value3);
    ival4 = (guint)atoi(value4);

    g_print("ENTRY VALUES = %s %s %s %s\n", value1, value2, value3, value4);
    g_print("ENTRY NUMS = %d %d %d %d\n", ival1, ival2, ival3, ival4);
}

int main (int argc, char *args[])
{
    GtkWidget *window, *vbox, *uptable, *downtable, *label;
    GtkWidget  *button, *button2;
    gtk_init(&argc, &args);

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_get_resizable(GTK_WINDOW(window));

    entrygrouped *eg;
    eg = g_slice_new(entrygrouped);

    vbox = gtk_vbox_new(FALSE, 2);
    uptable = gtk_table_new (3, 4, FALSE);
    downtable = gtk_table_new (3, 3, TRUE);

    label = gtk_label_new (" Enter the values to position the widget ");
    eg->value1 = gtk_entry_new();
    eg->value2 = gtk_entry_new();
    eg->value3 = gtk_entry_new();
    eg->value4 = gtk_entry_new();
    button = gtk_button_new_with_label ("Submit");
    button2 = gtk_button_new_with_label("BUTTON");

    gtk_table_attach_defaults (GTK_TABLE(uptable), label, 0, 3, 0, 1);
    gtk_table_attach_defaults (GTK_TABLE(uptable), eg->value1, 0, 1, 1, 2);
    gtk_table_attach_defaults (GTK_TABLE(uptable), eg->value2, 1, 2, 1, 2);
    gtk_table_attach_defaults (GTK_TABLE(uptable), eg->value3, 0, 1, 2, 3);
    gtk_table_attach_defaults (GTK_TABLE(uptable), eg->value4, 1, 2, 2, 3);
    gtk_table_attach_defaults (GTK_TABLE(uptable), button, 1, 2, 3, 4);

    gtk_widget_queue_draw(GTK_WIDGET(window));

    gtk_table_attach_defaults (GTK_TABLE(downtable), button2, ival1, ival2,
                                                                ival3, ival4);

    gtk_box_pack_start(GTK_BOX(vbox), uptable, 0, 0, 0);
    gtk_box_pack_start(GTK_BOX(vbox), downtable, 0, 0, 0);


    g_signal_connect_swapped(G_OBJECT(button), "clicked",
                                G_CALLBACK(button_clicked), eg);

    g_signal_connect_swapped(G_OBJECT(window), "destroy",
                                G_CALLBACK(gtk_main_quit), NULL);

    gtk_container_add (GTK_CONTAINER(window), vbox);
    gtk_widget_show_all(window);

    gtk_main();
    return 0;
}

Now whenever i open my application from terminal and enter some values and hit submit button, values are printed on terminal, but the problem is window did not draw the button2 with newly assigned values. I dont know any function which can refresh or redraw the whole window, though i tried the

while (gtk_events_pending())
  gtk_main_iteration();

above the button2 table attachment still i window do nothing. Do i need another callback function to resize window? Please help me with this problem.

EDIT : If my question is unclear i want to show it graphical way as follows

 ----------------------------
| a.out             _ [ ] x  |
 ----------------------------               before entering the 
| -------------------------- |              values 
||            |             ||
| -------------------------- |
||            |             ||
| -------------------------- |
|                   ________ |
|                  | Submit ||
|                   -------- |
 ----------------------------

 ----------------------------
| a.out             _ [ ] x  |
 ----------------------------               after entering the 
| -------------------------- |              values 
||           0 |          1 ||               
| -------------------------- |              button2 widget should be 
||           0 |          1 ||              redrawn according to the
| -------------------------- |              values entered and window
|                   ________ |              widget should be updated 
|                  | Submit ||
|                   -------- | 
|   _________                |
|  |  Button |               |
|   ---------                |
 ----------------------------

解决方案

After lots reading and frustration i finally able to solve my answer, The purpose of my application is to know how the table attachment works.

  1. Thus i did simple solution for problem. Which is attaching new button to a dialog box, Which is invoked after "clicked" event, the callback is as follows

static void fundia(GtkButton *button, GtkWindow *parent)
{
    GtkWidget *dialog, *table, *button2;
    dialog = gtk_dialog_new_with_buttons ("Information", parent,
                            GTK_DIALOG_MODAL, GTK_STOCK_OK, GTK_RESPONSE_OK,
                            NULL);
    button2 = gtk_button_new_with_label("BUTTON");

    table = gtk_table_new (3, 3, TRUE);
    gtk_table_attach_defaults (GTK_TABLE(table), button2, ival1, ival2,
                                    ival3, ival4);
    gtk_box_pack_start_defaults (GTK_BOX(GTK_DIALOG(dialog)->vbox), table);
    gtk_widget_show_all(dialog);

    gtk_dialog_run(GTK_DIALOG(dialog));
    gtk_widget_destroy(dialog);
}

where the callback function statement in main() is

g_signal_connect (G_OBJECT(button), "clicked", G_CALLBACK(fundia), (gpointer) window);

Though this function serves my purpose but above solution is irrelevant to this post's question hence it did not reuse or redraw the widget.

  1. Thus here is the final code of my program is as follows

#include <stdlib.h>
#include <gtk/gtk.h>
gboolean buttonbool = FALSE;

typedef struct {
    GtkWidget *value1, *value2, *value3, *value4;
} entrygrouped;

static GtkWidget *button2 = 0;

guint ival1, ival2, ival3, ival4;

void button_clicked (gpointer data, entrygrouped *widget)
{
    const gchar *cvalue1, *cvalue2, *cvalue3, *cvalue4;
    cvalue1 = gtk_entry_get_text (GTK_ENTRY(widget->value1));
    cvalue2 = gtk_entry_get_text (GTK_ENTRY(widget->value2));
    cvalue3 = gtk_entry_get_text (GTK_ENTRY(widget->value3));
    cvalue4 = gtk_entry_get_text (GTK_ENTRY(widget->value4));

    ival1 = (guint)atoi(cvalue1);
    ival2 = (guint)atoi(cvalue2);
    ival3 = (guint)atoi(cvalue3);
    ival4 = (guint)atoi(cvalue4);

    g_print("ENTRY VALUES = %s %s %s %s\n", cvalue1, cvalue2, cvalue3, cvalue4);
    g_print("ENTRY NUMS = %d %d %d %d\n", ival1, ival2, ival3, ival4);
}

void showid(gpointer data, GtkWidget *widget)
{
    if (buttonbool == TRUE)
    {
        /* Here reference count of the widget is decreased by 1. */
        gtk_container_remove(GTK_CONTAINER(widget), GTK_WIDGET(button2));

        /* In below statement reference count of widget increased by 1 */
        g_object_ref(button2);
        button2 = gtk_button_new_with_label("BUTTON");

        gtk_table_attach_defaults (GTK_TABLE(widget), button2, ival1, ival2,
                                                            ival3, ival4);
    } else {
        gtk_table_attach_defaults (GTK_TABLE(widget), button2, ival1, ival2,
                                                            ival3, ival4);
        buttonbool = TRUE;
    }

    gtk_widget_show(button2);
}

int main (int argc, char *args[])
{
    GtkWidget *window, *uptable, *downtable, *button, *vbox, *instr;

    gtk_init(&argc, &args);

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    gtk_window_set_title (GTK_WINDOW(window), "TABLEAPP");

    entrygrouped *eg;
    eg = g_slice_new(entrygrouped);

    instr = gtk_label_new (" Enter the values to position the widget ");
    uptable = gtk_table_new (2, 4, FALSE);
    downtable = gtk_table_new (3, 3, TRUE);
    button = gtk_button_new_with_label("Submit");   // Button with label
    button2 = gtk_button_new_with_label("SAME");
                                                    // Button with label
    vbox = gtk_vbox_new(FALSE, 2);                  // GTK vbox

    eg->value1 = gtk_entry_new();
    eg->value2 = gtk_entry_new();
    eg->value3 = gtk_entry_new();
    eg->value4 = gtk_entry_new();

    gtk_table_attach_defaults (GTK_TABLE(uptable), instr, 0, 3, 0, 1);
    gtk_table_attach_defaults (GTK_TABLE(uptable), eg->value1, 0, 1, 1, 2);
    gtk_table_attach_defaults (GTK_TABLE(uptable), eg->value2, 1, 2, 1, 2);
    gtk_table_attach_defaults (GTK_TABLE(uptable), eg->value3, 0, 1, 2, 3);
    gtk_table_attach_defaults (GTK_TABLE(uptable), eg->value4, 1, 2, 2, 3);
    gtk_table_attach_defaults (GTK_TABLE(uptable), button, 1, 2, 3, 4);

    /* The second arguments gtk_box_pack_start(); is about expand properties of
    widget which was set 0 and third is about allocation fill properties is also
    set 0 in my previous program. */
    gtk_box_pack_start (GTK_BOX(vbox), uptable, TRUE, TRUE, 0);
    gtk_box_pack_start (GTK_BOX(vbox), downtable, TRUE, TRUE, 0);

    g_signal_connect(G_OBJECT(button), "clicked",
                            G_CALLBACK(button_clicked), eg);

    g_signal_connect(G_OBJECT(button), "clicked",
                            G_CALLBACK(showid), downtable);

    g_signal_connect_swapped(G_OBJECT(window), "destroy",
                                G_CALLBACK(gtk_main_quit), NULL);

    gtk_container_add(GTK_CONTAINER(window), vbox);

    gtk_widget_show_all(window);

    gtk_main();
    return 0;
}

So I made following differences :-

  1. The gtk_box_pack_start(); functions second and third arguments is related to expand and fill properties was set to 0 in my previous program that means i don't have allocated any extra space for it.
  2. The button2 is only available to main(). Thus i declared the function above main() to accessible to all function.
  3. After attaching the button2 to downtable widget, when next time i am trying to reattach button2 to the table it was giving me a gtk_table_attach assertion child->parent == NULL failed error. So the previous reference needed to be free, thus the function gtk_container_remove()is added in showid callback function to decrease the reference count by 1. And i reference it again by g_object_ref to increase the reference counter by 1 to reference the widget again.

I want to thank Basile and Michi for there help, it was so helpful for me.

这篇关于如何刷新,在gtk中重画一个窗口(widget)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆