Re: Updating TextView and StatusBar problem



Hi Peter,

I followed your thread suggestion, and this code seems to work properly.
I hope that this can be of help for other people :)

Thanks.

Miguel

#include <stdio.h>
#include <unistd.h>
#include <gtk/gtk.h>
#include <pthread.h>

/* Aux data type */
typedef struct WINDOW{
        GtkWidget *window;
        GtkWidget *textview;
        GtkWidget *statusbar;
}windowT;

/* Prints something in status bar */
void print_statusbar (char *string, GtkStatusbar  *statusbar){
  
  gtk_statusbar_pop (statusbar, 0);

  gtk_statusbar_push (statusbar, 0, string);
}

/* Prints something in textview */
void print_textview(char *string, GtkTextView *textview){
        GtkTextBuffer *buffer;

        buffer = gtk_text_view_get_buffer (textview);
        
        gtk_text_buffer_insert_at_cursor(buffer, string, -1);
}

/* Thread func */
void *thread_func(void *args){
        windowT *window = (windowT*)args;
        
        gdk_threads_enter();
        print_textview("BLA\n", GTK_TEXT_VIEW(window->textview));
        print_statusbar(" Just printed BLA", GTK_STATUSBAR(window->statusbar));
        gdk_threads_leave();

        sleep(1);

        gdk_threads_enter();
        print_textview("BLE\n", GTK_TEXT_VIEW(window->textview));
        print_statusbar(" Just printed BLE", GTK_STATUSBAR(window->statusbar));
        gdk_threads_leave();
        
        return NULL;
}

/* Callback function */
void my_func(GtkButton *button, windowT *window){
        pthread_t tid;

        pthread_create(&tid, NULL, thread_func, window);
}


/* Main window */
windowT *create_window(){
        windowT *window;
        GtkWidget *vbox, *button;

        /* Main window */
        window->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_window_set_default_size (GTK_WINDOW (window->window),450, 450);
        g_signal_connect (window->window, "destroy",G_CALLBACK (gtk_main_quit),NULL);

        /* Vertical box */
        vbox = gtk_vbox_new(FALSE,0);
        gtk_container_add(GTK_CONTAINER(window->window), vbox);
        gtk_widget_show(vbox);

        /* Text view */
        window->textview = gtk_text_view_new();
        gtk_box_pack_start(GTK_BOX(vbox), window->textview, TRUE, TRUE, 0);
        gtk_text_view_set_editable (GTK_TEXT_VIEW (window->textview), FALSE);
        gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (window->textview), FALSE);
        gtk_widget_show(window->textview);

        /* Button */
        button = gtk_button_new_with_label("BUTTON");
        gtk_widget_show(button);
        gtk_box_pack_start(GTK_BOX(vbox), button, FALSE,FALSE, 0);
        g_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(my_func), 
window);

        /* Status bar */
        window->statusbar = gtk_statusbar_new();
        gtk_box_pack_start(GTK_BOX(vbox), window->statusbar, FALSE, FALSE, 0);
        gtk_widget_show(window->statusbar);

        return(window);
}

/* No comments ;) */
int main( int   argc,  char *argv[] ){
        windowT *window;
        
        g_thread_init(NULL);
        gdk_threads_init();     
        gtk_init (&argc, &argv);

        window = create_window();

        gtk_widget_show(window->window);

        gdk_threads_enter();
        gtk_main ();
        gdk_threads_leave();

        return(0);
}



On Monday 05 April 2004 10:16, Peter Krueger wrote:
On Sat, 3 Apr 2004, Miguel Figueiredo wrote:
I created a window which has a textview, a button and a statusbar. When I
press the button, I want to call a func that inserts text in both the
textview and the statusbar over a certain amount of time. The problem is
that this text is only visible when the function ends. The purpose is to
display the text as soon as it is inserted in the textview and/or
statusbar.

Hi Miguel,
GTK does its user interface updates in the main loop. When you press the
button the mainloop does not run until your event handler returns, that's
why you don't see the updates of your text changes. To overcome this you
can use
    while (gtk_events_pending()) {
      gtk_main_iteration();
    }
after you changed texts but before the time consuming task. When you
enter your callback you should call gtk_widget_set_sensitive(button,
false) to prevent that the user presses the button again before its first
event handling is finished. Right before exiting the callback enable it
again with gtk_widget_set_sensitive(button, true).

If your task is really time consuming (more than 1 second) you should do
it in a separate thread. A program with a graphical user interface should
always react to user input (like moving/resizing the window) and refresh
its display e.g. after it was covered by another application. Else the
user will think that your program crashed.

Regards,
                            Peter

-- 
Miguel Figueiredo
IT student / Marine Biologist
"If it ain't broken, don't fix it."




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]