如何使功能遵循正确的顺序?

时间:2014-01-11 13:55:17

标签: c gtk

我有这段代码:

#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;绘制窗口;销毁窗口;)。 这样,下载过程中屏幕为空,窗口被破坏后才能看到任何内容。

我一直在四处寻找并且没有找到任何关于此的信息,我该如何修复它以便遵循我希望它的顺序?

1 个答案:

答案 0 :(得分: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;
}