2014-01-11 49 views
0

我有這樣的代碼:如何使功能遵循正確的順序?

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

#include "splash_screen.h" 
#include "db.h" 

/* Global declarations */ 
GtkWidget *splash_window, *splash_image, *vbox, *pbar; 
int timer; 

/* A timeout to make the progressbar be animated */ 
static gboolean progress_timeout (gpointer data) 
{ 
    gtk_progress_bar_pulse (GTK_PROGRESS_BAR (data)); 

    /* Make this callback to be called again and again */ 
    return TRUE; 
} 

/* A function to destroy the splash screen */ 
static void destroy_splash_screen (GtkWidget *window, int timer) 
{ 
    /* Finish the timer */ 
    gtk_timeout_remove (timer); 
    timer = 0; 

    /* Destroy the widget window and its children */ 
    gtk_widget_destroy (GTK_WIDGET (window)); 
} 

/* Create the splash screen itself */ 
void splash_screen() 
{ 
    /* The screen */ 
    splash_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); 

    /* The properties */ 
    gtk_window_set_type_hint  (GTK_WINDOW (splash_window), GDK_WINDOW_TYPE_HINT_SPLASHSCREEN); 
    gtk_window_set_decorated  (GTK_WINDOW (splash_window), FALSE); 
    gtk_window_set_position   (GTK_WINDOW (splash_window), GTK_WIN_POS_CENTER_ALWAYS); 
    gtk_window_set_default_size  (GTK_WINDOW (splash_window), 300, 300); 
    gtk_window_set_resizable  (GTK_WINDOW (splash_window), FALSE); 
    gtk_window_set_title   (GTK_WINDOW (splash_window), "VadeTux [Cargando...]"); 
    gtk_container_set_border_width (GTK_CONTAINER (splash_window), 0); 

    /* The splash image */ 
    splash_image = gtk_image_new_from_file ("./imgs/splashscreen/end-splash.png"); 

    /* The vertical box */ 
    vbox = gtk_vbox_new (FALSE, 0); 

    /* Create the progress bar and make it pulse */ 
    pbar = gtk_progress_bar_new(); 
    gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pbar)); 
    /* The timer in charge of the animation */ 
    timer = g_timeout_add (100, progress_timeout, pbar); 

    /* Start the packing */ 
    gtk_container_add (GTK_CONTAINER (splash_window), vbox); 
    gtk_box_pack_start (GTK_BOX (vbox), splash_image, FALSE, FALSE, 0); 
    gtk_box_pack_start (GTK_BOX (vbox), pbar, FALSE, FALSE, 0); 

    /* Show everything */ 
    gtk_widget_show_all (splash_window); 

    get_page ("http://listadomedicamentos.aemps.gob.es/prescripcion.zip", "DB/prescripcion.zip"); 

    destroy_splash_screen (splash_window, timer); 
} 

編輯:(大部分包括是當我添加的解壓縮功能)

#include <curl/curl.h> 
#include <zip.h> 
#include <stdio.h> 
#include <string.h> 
#include <fcntl.h> 
#include <errno.h> 
#include <stdlib.h> 
#include <unistd.h> 

#include "db.h" 

void get_page (const char *url, const char *file_name) 
{ 
    CURL *easyhandle = curl_easy_init(); 
    curl_easy_setopt (easyhandle, CURLOPT_URL, url); 

    FILE *file = fopen (file_name, "w"); 

    curl_easy_setopt (easyhandle, CURLOPT_WRITEDATA, file); 
    curl_easy_perform (easyhandle); 

    curl_easy_cleanup (easyhandle); 
    fclose (file); 
} 

定時器和destroy_splash_screen是工作的好靜,而get_page()是一個CURL函數。問題是,它不會遵循(定義;創建窗口;繪製窗口;做get_page;銷燬窗口)的順序,它會做(定義;創建窗口;做get_page;繪製窗口;銷燬窗口)。 這樣,在下載過程中屏幕是空的,在你看到任何東西之前,窗口被銷燬。

我一直在環顧四周,並沒有發現任何關於此事,我該如何解決它,所以它遵循我希望它有的順序?

+0

代碼按照您提供的順序運行,但如果您不允許發生UI更新(例如由於在長時間運行的阻塞調用中使用CPU),您將不會視覺上能夠確認它。警告:這是一個通用的UI代碼概念,我不知道gtk細節。 – mah

+0

你的get_page函數是異步的嗎?即它不會等待函數在執行下一條語句之前完成(銷燬窗口) – Ervadac

+0

@Ervadac完全是,它似乎在窗口結束之前就開始了,並且無法找到一種方式告訴它在之後啓動,窗口已創建,但不能在get_page函數啓動之前進行繪製。它不會等待。不過,destroy函數在page_get之後工作。 – vitimiti

回答

1

這是一個帶有工作線程的Gtk +程序的幾乎最簡單的例子。該程序顯示進度條並打印輸入數字10秒。工人完成後你可以做其他事情。但是,由於GTK +本身不是線程安全的,因此您不應該從運行主循環的其他線程訪問任何線程的窗口小部件。

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

gboolean stop_program(gpointer unused) 
{ 
    /* Idle function run in the main thread. */ 
    gtk_main_loop(); 
    return FALSE; 
} 

gpointer worker_func(gpointer unused) 
{ 
    /* This code runs in the worker thread. */ 
    for (int i = 0; i < 10; ++i) { 
     printf("%d\n", i); 
     g_usleep(1000000); 
    } 

    g_idle_add(stop_program, NULL); 
    gtk_main_quit(); 

    return NULL; 
} 

gboolean progress_cb(gpointer user_data) 
{ 
    gtk_progress_bar_pulse(GTK_PROGRESS_BAR(user_data)); 
    return TRUE; 
} 

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

    GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 

    g_signal_connect(window, "delete_event", G_CALLBACK(gtk_main_quit), NULL); 

    GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6); 

    GtkWidget *progress = gtk_progress_bar_new(); 
    gtk_progress_bar_pulse(GTK_PROGRESS_BAR(progress)); 
    guint timer = g_timeout_add (100, progress_cb, progress); 

    gtk_box_pack_start(GTK_BOX(box), progress, TRUE, TRUE, 6); 
    gtk_container_add(GTK_CONTAINER(window), box); 

    gtk_widget_show_all(window); 

    /* Start the worker thread before starting the main loop. */ 
    GThread *thread = g_thread_new("worker thread", worker_func, NULL); 

    gtk_main(); 

    /* Wait for the thread to finish. */ 
    g_thread_join(thread); 

    return 0; 
} 
+0

這一直是大多數時間帶給我的問題,您可以簡單而快速地修復它,完美無瑕。萬億噸的感謝。 – vitimiti