GTK+ Forums Forum Index GTK+ Forums
Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Exposing a window during idle function execution

 
Post new topic   Reply to topic    GTK+ Forums Forum Index -> GTK+ Programming
Author Message
roscarby
Familiar Face


Joined: 27 Jun 2007
Posts: 5

PostPosted: Thu Jun 28, 2007 1:37 pm    Post subject: Exposing a window during idle function execution Reply with quote

I was trying to make a program
which draw lines requesting the end points
to the user via terminal, modifying scribble.c
I wrote the following code.

As you see the function draw_line is called
via g_idle_add. It happens that if I move a
whatever other window on the drawing area
while the draw_line function is waiting for me to insert
a new line, the lines and the drawing area deleted.
I would like to know what happens, and how to
avoid this.

This is my second day with gtk, so I would appreciate
also any other comment about the program and possible
hints.

Thanks in advance
Roscarby
Code: (Plaintext)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162


#include <gtk/gtk.h>
#include <glib/gstdio.h>

static gboolean configure_event( GtkWidget         *widget,
                                 GdkEventConfigure *event );
void quit_application(GtkWidget *w, gpointer user_data);

void on_event_after (GtkWidget *widget,
                GdkEvent *event,
                gpointer user_data);

static GdkPixmap *pixmap = NULL;
GtkWidget *darea;


int dareaexist=0;
int main_start=0;


gboolean draw_line()
{
char c;
int x1,y1,x2,y2;
if(dareaexist>=0)
{
    while(getchar()!='\n');
    g_printf("Do you want to add a line (y/n) : ");
    scanf("%c",&c);
    if(c=='y')
        {
        g_printf("Insert 1st point x y:  ");
        scanf("%d %d",&x1,&y1);
        g_printf("Insert 2nd point x y:  ");
        scanf("%d %d",&x2,&y2);

        gdk_draw_line(darea->window,
         darea->style->black_gc,
         x1,y1,x2,y2
         );
    }
else
    gtk_main_quit();
return TRUE;
};
}

static gboolean configure_event( GtkWidget         *widget,
                                 GdkEventConfigure *event )
{
  if (pixmap)
  g_object_unref (pixmap);

  pixmap = gdk_pixmap_new (widget->window,
                           widget->allocation.width,
                           widget->allocation.height,
                           -1);
  gdk_draw_rectangle (pixmap,
                      widget->style->white_gc,
                      TRUE,
                      0, 0,
                      widget->allocation.width,
                      widget->allocation.height);

  return TRUE;
}


static gboolean expose_event( GtkWidget      *widget,
                              GdkEventExpose *event )
{

  gdk_draw_drawable (widget->window,
                     widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
                     pixmap,
                     event->area.x, event->area.y,
                     event->area.x, event->area.y,
                     event->area.width, event->area.height);

  return FALSE;
}



int
main (int argc, char *argv[])
{

        GtkWidget *window;
   
    /* initialize the GTK+ library */
        gtk_init (&argc, &argv);

        /* create main window */
        window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

    gtk_window_set_title (GTK_WINDOW (window), "Example");
        gtk_container_set_border_width (GTK_CONTAINER (window), 0);
        gtk_widget_set_size_request (window, 200, 100);

        /* connect signals */
        g_signal_connect (G_OBJECT(window), "destroy",
                        G_CALLBACK (quit_application), NULL);
    g_signal_connect (G_OBJECT(window), "event-after",
                G_CALLBACK (on_event_after), NULL);


    gtk_widget_set_size_request(GTK_WIDGET(window),400,400);

    gtk_widget_show (window);

   
    g_idle_add(draw_line,NULL;
           gtk_main ();
       
        return 0;     
}


void quit_application(GtkWidget *w, gpointer user_data)
{
gtk_main_quit();
}


void
on_event_after (GtkWidget *widget,
                GdkEvent *event,
                gpointer user_data)
{
 //  g_printf("event type: %d   \n",event->type);
   if ((event->type == GDK_EXPOSE)&&(main_start==0))
   {
       
        char c;
    g_printf("Do you want to create a drawing area:   ");
    scanf("%c",&c);
    main_start = 1;
    if (c=='y')
    {

    dareaexist=1;
   
    darea  = gtk_drawing_area_new();
    gtk_widget_set_size_request(GTK_WIDGET(darea),400,400);
    gtk_container_add (GTK_CONTAINER (widget), darea);

    g_signal_connect (G_OBJECT (darea),"configure_event",
                    G_CALLBACK (configure_event), NULL);
    g_signal_connect (G_OBJECT (darea), "expose_event",
                    G_CALLBACK (expose_event), NULL);

    gtk_widget_show(darea);
   
    }


   }
}

Back to top
openldev
Never Seen the Sunlight


Joined: 21 Sep 2005
Posts: 387
Location: Fairfax, Virginia

PostPosted: Thu Jun 28, 2007 7:35 pm    Post subject: Reply with quote

The reason is because, every time an expose-event occurs, the widget is cleared. So, you must redraw your widget on expose-event.
Back to top
roscarby
Familiar Face


Joined: 27 Jun 2007
Posts: 5

PostPosted: Mon Jul 02, 2007 2:53 pm    Post subject: Reply with quote

Well, it took me some time to get close to the solution,
but I think I am on the good way, I solved the problem by
using thread and not idle functions, the corrected code is
now:

Code: (Plaintext)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230


#include <gtk/gtk.h>
#include <glib/gstdio.h>
#include <pthread.h>



static gboolean configure_event( GtkWidget         *widget,
                                 GdkEventConfigure *event );
void   quit_application(GtkWidget *w, gpointer user_data);
void   on_window_map (GtkWidget*, gpointer);
void   on_window_realize (GtkWidget*, gpointer);
void   on_window_show (GtkWidget*, gpointer);
static gboolean expose_event( GtkWidget      *widget,
                              GdkEventExpose *event );
void
on_event_after (GtkWidget *widget,
                GdkEvent *event,
                gpointer user_data);

static GdkPixmap *pixmap = NULL;


int dareaexist=0;
int main_start=0;

GtkWidget *window;
GtkWidget *darea;

void* draw_line(void* arg)
{
GdkEventExpose *event;
char c;
int x1,y1,x2,y2;
int h,w;
c='y';
do
{
if(dareaexist>0)
{
    while(getchar()!='\n');
    g_printf("Do you want to add a line (y/n) : ");
    scanf("%c",&c);
    if(c=='y')
        {
        g_printf("Insert 1st point x y:  ");
        scanf("%d %d",&x1,&y1);
        g_printf("Insert 2nd point x y:  ");
        scanf("%d %d",&x2,&y2);


        gdk_threads_enter();

        gdk_draw_line(pixmap,
         darea->style->black_gc,
         x1,y1,x2,y2
         );

        gdk_window_get_size(pixmap, &w, &h);

        gdk_draw_pixmap(darea->window,
                darea->style->fg_gc[GTK_WIDGET_STATE (darea)],
                pixmap,
                0,
                0,
                0,
                0,
                w,
                h );

        gtk_widget_queue_draw (darea);
        gdk_threads_leave();

        };

};
}while(c!='n');
gtk_main_quit();
}

static gboolean configure_event( GtkWidget         *widget,
                                 GdkEventConfigure *event )
{
  if (pixmap)
  g_object_unref (pixmap);

  pixmap = gdk_pixmap_new (widget->window,
                           widget->allocation.width,
                           widget->allocation.height,
                           -1);
   gdk_draw_rectangle (pixmap,
                      widget->style->white_gc,
                      TRUE,
                      0, 0,
                      widget->allocation.width,
                      widget->allocation.height);

   
  return TRUE;
}


static gboolean expose_event( GtkWidget      *widget,
                              GdkEventExpose *event )
{


  gdk_draw_drawable (widget->window,
                     widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
                     pixmap,
                     event->area.x, event->area.y,
                     event->area.x, event->area.y,
                     event->area.width, event->area.height);

  return FALSE;
}



int
main (int argc, char *argv[])
{




       
   
    pthread_t tid;

         
    /* initialize the GTK+ library */

    g_thread_init(NULL);
    gdk_threads_init();
    gdk_threads_enter();


        gtk_init (&argc, &argv);

        /* create main window */
        window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

    gtk_window_set_title (GTK_WINDOW (window), "Example");
        gtk_container_set_border_width (GTK_CONTAINER (window), 0);
        gtk_widget_set_size_request (window, 200, 100);

    g_signal_connect (G_OBJECT(window), "event-after",
                G_CALLBACK (on_event_after), NULL);



    gtk_widget_set_size_request(GTK_WIDGET(window),400,400);
   
    gtk_widget_show (window);

    pthread_create(&tid,NULL,draw_line,NULL);
   
           gtk_main ();
    gdk_threads_leave();
       
        return 0;     
}


void quit_application(GtkWidget *w, gpointer user_data)
{
gtk_main_quit();
}


void
on_window_map (GtkWidget *w,gpointer user_data)
{
        g_print("Window was mapped.\n");
}

void
on_window_realize (GtkWidget *w,gpointer user_data)
{
        g_print("Window was realized.\n");

}

void
on_window_show (GtkWidget *w,gpointer user_data)
{
        g_print("Window was shown.\n");

   
   
}



void
on_event_after (GtkWidget *widget,
                GdkEvent *event,
                gpointer user_data)
{
 //  g_printf("event type: %d   \n",event->type);
   if ((event->type == GDK_EXPOSE)&&(main_start==0))
   {
        char c;
    g_printf("Do you want to create a drawing area:   ");
    scanf("%c",&c);
    main_start = 1;
    if (c=='y')
    {

    dareaexist=1;
   
    darea  = gtk_drawing_area_new();
    gtk_widget_set_size_request(GTK_WIDGET(darea),400,400);
    gtk_container_add (GTK_CONTAINER (widget), darea);

     g_signal_connect (G_OBJECT (darea),"configure_event",
                     G_CALLBACK (configure_event), NULL);
     g_signal_connect (G_OBJECT (darea), "expose_event",
                     G_CALLBACK (expose_event), NULL);

    gtk_widget_show(darea);
   
    }
   }
}



to be compiled with `pkg-config --cflags --libs gtk+-2.0 gthread-2.0`

I would like to have opinions about the solution particularly is it correct?
Could I do the same without using threads?
Hints about possible improvements.. i am just learning gtk+ and c together so any advice would be welcome.

Thanx a lot
roscarby
Back to top
Display posts from previous:   
Post new topic   Reply to topic    GTK+ Forums Forum Index -> GTK+ Programming All times are GMT
Page 1 of 1

 


Powered by phpBB © 2001, 2005 phpBB Group
CodeBB 1.0 Beta 2
Protected by Anti-Spam ACP