一個進度條的產生是透過 gtk_progress_bar_new,進度條的範圍是[0,1],且以浮點數儲存。如果要讀取或修改進度條的數值利用 gtk_progress_bar_set(get)_fraction。了解這些之後,咱們就來看看程式碼。
/*
以下程式執行會產生一個主視窗+按鍵
當按下按鍵就建立另一個視窗+進度條
並且透過計時器每次增加0.01,直到1.0為止
*/
#include<gtk/gtk.h>
gdouble new_val;
guint timer_id = 0;
static gboolean flush_progressbar(gpointer progressbar)
{
new_val= gtk_progress_bar_get_fraction(GTK_PROGRESS_BAR(progressbar))+0.01;
if(new_val >= 1.0) new_val = 1.0;
gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progressbar), new_val);
if(new_val >= 1.0) {
/* 舊版是用 gtk_timeout_remove() */
g_source_remove(timer_id);
return FALSE;
}
return TRUE; // 如此計時器才會一直 work
}
static void create_window(GtkWidget *widget, gpointer window)
{
// 產生並初始化視窗
...
GtkWidget *progressbar;
progressbar = gtk_progress_bar_new();
gtk_layout_put(GTK_LAYOUT(layout), progressbar, 100, 200);
...
// 100毫秒執行一次
/* 舊版是用 gtk_timeout_add() */
timeId = g_timeout_add(100 , flush_progressbar, progressbar);
}
int main(int argc, char *argv[])
{
// window - 主視窗
// window_create_after - 按下按鍵後產生的視窗
GtkWidget *window;
GtkWidget *window_create_after;
GtkWidget *button;
gtk_set_locale();
gtk_init(&argc, &argv);
// 產生並初始化 window
// 產生並出使化 button、加到 window 中
// 註冊 clicked 事件用來產生 window_create_after
// 以及產生一個 timer
gtk_main();
return(0);
}
這裡要注意的有兩點:
- 不要計時器中加入 delay 的機制(如:sleep),因為會導致前一次沒處理完,下一次又開始處理(re-entrant routine),導致 stack overflow。
- 不要讓主程式(main process)去處理 progressbar 的值,因為只會看到最終完成的畫面,中間的遞增過程使用者看不到。會有這種結果其實也不難想像,由於主程式正在執行某個function call,即使你不斷地更新進度條的內容,這些 event handler 只能等到目前的程式執行完,控制權回到 caller (也許好幾層),才會去執行這些更新畫面的 handler。
最後再介紹兩支和進度條相關的函式:
gtk_progress_bar_set_pulse_step(GTK_PROGRESS_BAR(progressbar),0.1);
gtk_progress_bar_pulse(GTK_PROGRESS_BAR(progressbar));
這兩支函式可以讓進度條內的東東左跑右跑,就是放入 Live CD,在 ubuntu 圖樣的那個畫面,進度條開始跑進度之前的行為。就如同以上的程式碼,每次以0.1的間隔在移動,移動完右邊,就移左邊;移動完左邊,就移動右邊。
沒有留言:
張貼留言