C 使用gtk控制多线程进度条
在我的C程序中,从internet下载一些文件,我使用GTK进度条显示下载进度 我想如果我下载一个文件,我的应用程序会显示一个进度条 如果我下载三个文件,我的应用程序可以显示三个进度条。其余的都可以用同样的方式完成 我用glade3创建UI。GtkTreeView 有3列C 使用gtk控制多线程进度条,c,curl,gtk,glade,C,Curl,Gtk,Glade,在我的C程序中,从internet下载一些文件,我使用GTK进度条显示下载进度 我想如果我下载一个文件,我的应用程序会显示一个进度条 如果我下载三个文件,我的应用程序可以显示三个进度条。其余的都可以用同样的方式完成 我用glade3创建UI。GtkTreeView 有3列 名字 进展 地位 我写了一些代码,它可以工作,但有一些问题 如果我下载一个文件,应用程序lonking还不错 但如果我下载两个文件。 应用程序无法显示两个进度条 应用程序只显示一个进程中的两个线程 我该如何解决它 和源代码:
/*
gcc -Wall -g `pkg-config --cflags --libs gtk+-2.0 gmodule-export-2.0` -lcurl -lgthread-2.0 liststore.c -o liststore
*/
#include <stdio.h>
#include <gtk/gtk.h>
#include <glib.h>
#include <unistd.h>
#include <pthread.h>
#include <curl/curl.h>
#include <curl/types.h> /* new for v7 */
#include <curl/easy.h> /* new for v7 */
gchar *URL = "http://soundclash-records.co.uk/mp3s/upfull_rockers_never_gonna_let_you_down.mp3";
size_t my_write_func(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
return fwrite(ptr, size, nmemb, stream);
}
size_t my_read_func(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
return fread(ptr, size, nmemb, stream);
}
typedef struct _Data Data;
struct _Data
{
GtkWidget *down; /* Down button */
GtkWidget *tree; /* Tree view */
gdouble progress;
};
enum
{
STRING_COLUMN,
INT_COLUMN,
N_COLUMNS
};
gboolean set_download_progress(gpointer data)
{
Data *treeview = (Data *)data;
GtkListStore* store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(treeview->tree)));
GtkTreeIter iter;
gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store) ,
&iter,
g_strdup_printf ("%d",0));
gtk_list_store_set(store, &iter,
INT_COLUMN,treeview->progress, -1);
return FALSE;
}
int my_progress_func(Data *data,
double t, /* dltotal */
double d, /* dlnow */
double ultotal,
double ulnow)
{
// printf("%d / %d (%g %%)\n", d, t, d*100.0/t);
gdk_threads_enter();
gdouble progress;
progress = d*100.0/t;
data->progress = progress;
g_idle_add(set_download_progress, data);
gdk_threads_leave();
return 0;
}
void *create_thread(void *data)
{
Data *viewtree = (Data *)data;
GtkTreeIter iter;
GtkListStore* store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(viewtree->tree)));
gtk_list_store_append( store, &iter );
g_print("url\n");
CURL *curl;
CURLcode res;
FILE *outfile;
gchar *url = URL;
curl = curl_easy_init();
if(curl)
{
outfile = fopen("test.curl", "w");
if(outfile)
g_print("curl\n");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_write_func);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, my_read_func);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, my_progress_func);
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, data);
res = curl_easy_perform(curl);
fclose(outfile);
/* always cleanup */
curl_easy_cleanup(curl);
}
g_object_unref( G_OBJECT( store ) );
return NULL;
}
G_MODULE_EXPORT void
cb_add( GtkWidget *button,
Data *data )
{
if (!g_thread_create(&create_thread, data, FALSE, NULL) != 0)
g_warning("can't create the thread");
}
int main(int argc, char **argv)
{
GtkBuilder *builder;
GtkWidget *window;
Data *data;
curl_global_init(CURL_GLOBAL_ALL);
if( ! g_thread_supported() )
g_thread_init( NULL );
gdk_threads_init();
gtk_init(&argc, &argv);
data = g_slice_new( Data );
/* Create builder */
builder = gtk_builder_new();
gtk_builder_add_from_file( builder, "progress.glade", NULL );
window = GTK_WIDGET( gtk_builder_get_object( builder, "window1" ) );
data->down = GTK_WIDGET( gtk_builder_get_object( builder, "down" ) );
data->tree = GTK_WIDGET( gtk_builder_get_object( builder, "treeview" ) );
gtk_builder_connect_signals( builder, data );
g_object_unref( G_OBJECT( builder ) );
gtk_widget_show( window );
gtk_main();
g_slice_free( Data, data );
return 0;
}
/*
gcc-Wall-g`pkg config--cflags--libs gtk+-2.0 gmodule-export-2.0`-lcurl-lgthread-2.0 liststore.c-o liststore
*/
#包括
#包括
#包括
#包括
#包括
#包括
#包括/*v7的新功能*/
#包括/*v7的新功能*/
gchar*URL=”http://soundclash-records.co.uk/mp3s/upfull_rockers_never_gonna_let_you_down.mp3";
大小\我的写入\函数(void*ptr、大小\ t size、大小\ t nmemb、文件*流)
{
返回fwrite(ptr、大小、nmemb、流);
}
大小为my\u read\u func(无效*ptr,大小为,大小为nmemb,文件为*流)
{
返回fread(ptr、大小、nmemb、流);
}
typedef结构数据;
结构数据
{
GtkWidget*向下;/*向下按钮*/
GtkWidget*树;/*树视图*/
双倍进步;
};
枚举
{
字符串_列,
INT_栏,
N_列
};
gboolean设置\下载\进度(gpointer数据)
{
数据*树视图=(数据*)数据;
GtkListStore*store=GTK_列表_存储(GTK_树视图_获取模型(GTK_树视图(treeview->tree)));
GtkTreeIter iter;
gtk_树模型从字符串获取iter_(gtk_树模型(存储),
&国际热核聚变实验堆,
g_strdup_printf(“%d”,0));
gtk_列表_存储_集(存储和iter,
INT_列,树状视图->进度,-1);
返回FALSE;
}
int my_progress_func(数据*数据,
双t,/*dltotal*/
双d,/*dlnow*/
双ultotal,
双ulnow)
{
//printf(“%d/%d(%g%%)\n”,d,t,d*100.0/t);
gdk_threads_enter();
双倍进步;
进度=d*100.0/t;
数据->进度=进度;
g\u空闲\u添加(设置\u下载\u进度、数据);
gdk_线程_离开();
返回0;
}
void*创建线程(void*数据)
{
数据*视图树=(数据*)数据;
GtkTreeIter iter;
GtkListStore*store=GTK_列表_存储(GTK_树视图_获取模型(GTK_树视图(viewtree->tree)));
gtk列表、存储、附加(存储和iter);
g_print(“url\n”);
卷曲*卷曲;
卷曲编码;
文件*输出文件;
gchar*url=url;
curl=curl_easy_init();
if(curl)
{
outfile=fopen(“测试卷曲度”,“w”);
如果(输出文件)
g_print(“curl\n”);
curl_easy_setopt(curl,CURLOPT_URL,URL);
curl_easy_setopt(curl,CURLOPT_WRITEDATA,outfile);
curl\u easy\u setopt(curl,CURLOPT\u WRITEFUNCTION,my\u write\u func);
curl\u easy\u setopt(curl,CURLOPT\u READFUNCTION,my\u read\u func);
curl\u easy\u setopt(curl,CURLOPT\u NOPROGRESS,FALSE);
curl\u easy\u setopt(curl,CURLOPT\u PROGRESSFUNCTION,my\u progress\u func);
curl_easy_setopt(curl,CURLOPT_PROGRESSDATA,data);
res=旋度(curl)\u容易执行(curl);
fclose(输出文件);
/*总是清理*/
旋度\轻松\清洁(旋度);
}
g_object_unref(g_object(store));
返回NULL;
}
G_模块_导出无效
cb_添加(GtkWidget*按钮,
数据*数据)
{
如果(!g_thread_create(&create_thread,data,FALSE,NULL)!=0)
g_警告(“无法创建线程”);
}
int main(int argc,字符**argv)
{
GtkBuilder*builder;
GtkWidget*窗口;
数据*数据;
curl\u global\u init(curl\u global\u ALL);
如果(!g_thread_supported())
g_thread_init(NULL);
gdk_线程_init();
gtk_init(&argc,&argv);
数据=g_切片_新(数据);
/*创建生成器*/
builder=gtk_builder_new();
gtk_builder_从_文件添加_(builder,“progress.glade”,NULL);
窗口=GTK_小部件(GTK_生成器_获取对象(生成器,“窗口1”);
data->down=GTK_小部件(GTK_builder_get_对象(builder,“down”));
数据->树=GTK_小部件(GTK_生成器_获取_对象(生成器,“树视图”));
gtk建筑商连接信号(建筑商,数据);
g_object_unref(g_object(builder));
gtk_widget_show(窗口);
gtk_main();
g_片_自由(数据,数据);
返回0;
}
=========================================================
更新:12-11-09
/*
gcc -Wall -g `pkg-config --cflags --libs gtk+-2.0 gmodule-export-2.0 gthread-2.0 libcurl` liststore2.c -o liststore2
*/
#include <stdio.h>
#include <gtk/gtk.h>
#include <glib.h>
#include <unistd.h>
#include <pthread.h>
#include <curl/curl.h>
#include <curl/types.h> /* new for v7 */
#include <curl/easy.h> /* new for v7 */
gchar *URL = "http://soundclash-records.co.uk/mp3s/upfull_rockers_never_gonna_let_you_down.mp3";
static GHashTable* TreeRowReferences;
static GPrivate* current_data_key = NULL;
size_t my_write_func(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
return fwrite(ptr, size, nmemb, stream);
}
size_t my_read_func(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
return fread(ptr, size, nmemb, stream);
}
typedef struct _Data Data;
struct _Data
{
GtkWidget *down; /* Down button */
GtkWidget *tree; /* Tree view */
gdouble progress;
};
enum
{
STRING_COLUMN,
INT_COLUMN,
N_COLUMNS
};
gboolean set_download_progress(gpointer data)
{
Data *treeview = (Data *)data;
GtkListStore* store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(treeview->tree)));
GtkTreeIter iter;
GtkTreeRowReference* reference = g_hash_table_lookup(TreeRowReferences,data);
GtkTreePath* path = gtk_tree_row_reference_get_path(reference);
gtk_tree_model_get_iter(GTK_TREE_MODEL(store),
&iter, path);
gtk_list_store_set(store, &iter,
INT_COLUMN,treeview->progress, -1);
gtk_tree_path_free (path);
return FALSE;
}
int my_progress_func(Data *data,
double t, /* dltotal */
double d, /* dlnow */
double ultotal,
double ulnow)
{
if(t == 0)
return 0;
data->progress = d*100.0/t;
gdk_threads_enter();
g_idle_add(set_download_progress, data);
gdk_threads_leave();
return 0;
}
void *create_thread(void *data)
{
Data *current_treeview = g_private_get (current_data_key);
if (!current_treeview)
{
current_treeview = g_new (Data, 1);
current_treeview = (Data *)data;
g_private_set (current_data_key, current_treeview);
g_print("p %g\n",current_treeview->progress);
}
else{
current_treeview = (Data *)data;
g_print("c %g\n",current_treeview->progress);
}
g_print("url\n");
CURL *curl;
CURLcode res;
FILE *outfile;
gchar *url = URL;
gdk_threads_enter();
curl = curl_easy_init();
if(curl)
{
outfile = fopen("test.curl", "w");
if(outfile)
g_print("curl\n");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, outfile);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_write_func);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, my_read_func);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE);
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, my_progress_func);
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, current_treeview);
gdk_threads_leave();
res = curl_easy_perform(curl);
fclose(outfile);
/* always cleanup */
curl_easy_cleanup(curl);
}
return NULL;
}
G_MODULE_EXPORT void
cb_add( GtkWidget *button,
Data *data )
{
Data *current_download = (Data *)data;
GtkTreeIter iter;
GtkListStore* store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(current_download->tree)));
gtk_list_store_append( store, &iter );
GtkTreeRowReference* reference = NULL;
GtkTreePath* path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter);
reference = gtk_tree_row_reference_new(GTK_TREE_MODEL(store), path);
g_hash_table_insert(TreeRowReferences, current_download, reference);
gtk_tree_path_free(path);
if (!g_thread_create(&create_thread, current_download, FALSE, NULL) != 0)
g_warning("can't create the thread");
}
int main(int argc, char **argv)
{
GtkBuilder *builder;
GtkWidget *window;
Data *data;
curl_global_init(CURL_GLOBAL_ALL);
if( ! g_thread_supported() )
g_thread_init( NULL );
gdk_threads_init();
gtk_init(&argc, &argv);
data = g_slice_new( Data );
/* Create builder */
builder = gtk_builder_new();
gtk_builder_add_from_file( builder, "progress.glade", NULL );
window = GTK_WIDGET( gtk_builder_get_object( builder, "window1" ) );
data->down = GTK_WIDGET( gtk_builder_get_object( builder, "down" ) );
data->tree = GTK_WIDGET( gtk_builder_get_object( builder, "treeview" ) );
TreeRowReferences = g_hash_table_new(NULL, NULL);
gtk_builder_connect_signals( builder, data );
g_object_unref( G_OBJECT( builder ) );
gdk_threads_enter();
gtk_widget_show( window );
gdk_threads_leave();
gtk_main();
g_slice_free( Data, data );
return 0;
}
/*
gcc-Wall-g`pkg config--cflags--libs gtk+-2.0 gmodule-export-2.0 gthread-2.0 libcurl`liststore2.c-o liststore2
*/
#包括
#包括
#包括
#包括
#包括
#包括
#包括/*v7的新功能*/
#包括/*v7的新功能*/
gchar*URL=”http://soundclash-records.co.uk/mp3s/upfull_rockers_never_gonna_let_you_down.mp3";
静态GHashTable*树引用;
静态GPrivate*当前数据密钥=NULL;
大小\我的写入\函数(void*ptr、大小\ t size、大小\ t nmemb、文件*流)
{
返回fwrite(ptr、大小、nmemb、流);
}
大小为my\u read\u func(无效*ptr,大小为,大小为nmemb,文件为*流)
{
返回fread(ptr、大小、nmemb、流);
}
typedef结构数据;
结构数据
{
GtkWidget*向下;/*向下按钮*/
GtkWidget*树;/*树视图*/
双倍进步;
};
枚举
{
字符串_列,
INT_栏,
N_列
};
gboolean设置\下载\进度(gpointer数据)
{
数据*树视图=(数据*)数据;
GtkListStore*store=GTK_列表_存储(GTK_树视图_获取模型(GTK_树视图(treeview->tree)));
GtkTreeIter iter;
GtkTreeRowReference*reference=g_哈希_表_查找(树引用,数据);
GtkTreePath*path=gtk_树_行_参考_获取_路径(参考);
gtk_tree_mo
gcc -Wall -g `pkg-config --cflags --libs gtk+-2.0 gmodule-export-2.0 gthread-2.0 libcurl` liststore.c -o liststore
int my_progress_func(Data *data,
double t, /* dltotal */
double d, /* dlnow */
double ultotal,
double ulnow)
{
if(t == 0)
return 0;
data->progress = d*100.0/t;
gdk_threads_enter();
g_idle_add(set_download_progress, data);
gdk_threads_leave();
return 0;
}
gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store) ,
&iter,
g_strdup_printf ("%d",0));
gtk_tree_model_get_iter(gtk_tree_row_reference_get_model(row_reference), &iter, gtk_tree_row_reference_get_path(row_reference));