- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
在我的 C 程序中,从 Internet 下载一些文件,我使用 GTK 进度条显示下载进度。
我想如果我下载一个文件,我的应用程序会显示一个进度条
如果我下载三个文件,我的应用程序可以显示三个进度条。其余的可以用同样的方式完成。
i create UI with glade3. GtkTreeViewhave 3 columns
- Name
- Progress
- Status
我写了一些代码,它可以工作但有一些问题
如果我下载一个文件,应用程序会很不错。
但是如果我下载两个文件。应用无法显示两个进度条。
app 一次只显示两个线程
我该如何解决?
和源代码:
/*
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;
}
============================================= ==========
更新: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;
}
最佳答案
以下是让您的代码正常工作的提示:
如果库有 pkg-config 文件,例如 gthread 或 libcurl,则使用它而不是混合调用 pkg-config 和 -l
开关。这不是问题所在,但以后可能会给您带来麻烦。所以像这样编译你的文件:
gcc -Wall -g `pkg-config --cflags --libs gtk+-2.0 gmodule-export-2.0 gthread-2.0 libcurl` liststore.c -o liststore
如果使用线程,总是,总是,总是,将对 gtk_main()
的调用包装在 gdk_threads_enter()
和gdk_threads_leave()
。这也不是问题所在,但以后肯定会给您带来麻烦。
下一步,消除控制台中喷涌而出的所有警告。如果错误生成的警告未在其他 50 条警告中丢失,则更容易发现错误。这些警告 确实 意味着您做错了什么,所以不要忽略它们。
一个。我收到的第一个警告是提示 NaN。 NaN 代表“不是数字”,它是除以零时得到的结果。您的代码中唯一的划分是在 my_progress_func()
中,因此 CURL 有时可能会传入零作为 dltotal
参数。如果您检查它,它会消除这些警告:
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;
}
下一个警告原因是 thread_create()
末尾的 unref 语句。您正在做的是使用 gtk_tree_view_get_model()
从 TreeView 中获取模型,但这并没有为您提供模型的引用。因此,当您取消引用它时,您实际上是在破坏模型,而 TreeView 仍在使用它。删除该语句,所有警告都会神奇地消失。您根本不需要取消引用模型。 TreeView 拥有对它的唯一引用,当 TreeView 被销毁时,它会自动取消对模型的引用。不过,这仍然不是问题。
现在一切都已解决,您可以确定问题不是由某些无效指针或线程问题引起的。事实证明这毕竟是一件非常简单的事情:
gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (store) ,
&iter,
g_strdup_printf ("%d",0));
在这里,您总是得到一个指向行号 0 的 iter,即第一行。这就是为什么所有下载进度都显示在第一行的原因。我建议使用 GPrivate
来让每线程数据结构具有自己的进度分数,并为您在启动线程时创建的行使用 GtkTreeRowReference
。获取 CURL 以将该数据结构发送到回调。 不要使用GtkTreeIter
或GtkTreePath
来存储行。相反,像这样获取你的 GtkTreeIter
:
gtk_tree_model_get_iter(gtk_tree_row_reference_get_model(row_reference), &iter, gtk_tree_row_reference_get_path(row_reference));
祝你好运。
关于c - 使用 gtk 的多线程进度条控制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1878783/
我将 Bootstrap 与 css 和 java 脚本结合使用。在不影响前端代码的情况下,我真的很难在css中绘制这个背景。在许多问题中,人们将宽度和高度设置为 0%。但是由于我的导航栏,我不能使用
我正在用 c 编写一个程序来读取文件的内容。代码如下: #include void main() { char line[90]; while(scanf("%79[^\
我想使用 javascript 获取矩阵数组的所有对 Angular 线。假设输入输出如下: input = [ [1,2,3], [4,5,6], [7,8,9], ] output =
可以用pdfmake绘制lines,circles和other shapes吗?如果是,是否有documentation或样本?我想用jsPDF替换pdfmake。 最佳答案 是的,有可能。 pdfm
我有一个小svg小部件,其目的是显示角度列表(参见图片)。 现在,角度是线元素,仅具有笔触,没有填充。但是现在我想使用一种“内部填充”颜色和一种“笔触/边框”颜色。我猜想line元素不能解决这个问题,
我正在为带有三角对象的 3D 场景编写一个非常基本的光线转换器,一切都工作正常,直到我决定尝试从场景原点 (0/0/0) 以外的点转换光线。 但是,当我将光线原点更改为 (0/1/0) 时,相交测试突
这个问题已经有答案了: Why do people write "#!/usr/bin/env python" on the first line of a Python script? (22 个回
如何使用大约 50 个星号 * 并使用 for 循环绘制一条水平线?当我尝试这样做时,结果是垂直(而不是水平)列出 50 个星号。 public void drawAstline() { f
这是一个让球以对角线方式下降的 UI,但球保持静止;线程似乎无法正常工作。你能告诉我如何让球移动吗? 请下载一个球并更改目录,以便程序可以找到您的球的分配位置。没有必要下载足球场,但如果您愿意,也可以
我在我的一个项目中使用 Jmeter 和 Ant,当我们生成报告时,它会在报告中显示 URL、#Samples、失败、成功率、平均时间、最短时间、最长时间。 我也想在报告中包含 90% 的时间线。 现
我有一个不寻常的问题,希望有人能帮助我。我想用 Canvas (android) 画一条 Swing 或波浪线,但我不知道该怎么做。它将成为蝌蚪的尾部,所以理想情况下我希望它的形状更像三角形,一端更大
这个问题已经有答案了: Checking Collision of Shapes with JavaFX (1 个回答) 已关闭 8 年前。 我正在使用 JavaFx 8 库。 我的任务很简单:我想检
如何按编号的百分比拆分文件。行数? 假设我想将我的文件分成 3 个部分(60%/20%/20% 部分),我可以手动执行此操作,-_-: $ wc -l brown.txt 57339 brown.tx
我正在努力实现这样的目标: 但这就是我设法做到的。 你能帮我实现预期的结果吗? 更新: 如果我删除 bootstrap.css 依赖项,问题就会消失。我怎样才能让它与 Bootstrap 一起工作?
我目前正在构建一个网站,但遇到了 transform: scale 的问题。我有一个按钮,当用户将鼠标悬停在它上面时,会发生两件事: 背景以对 Angular 线“扫过” 按钮标签颜色改变 按钮稍微变
我需要使用直线和仿射变换绘制大量数据点的图形(缩放图形以适合 View )。 目前,我正在使用 NSBezierPath,但我认为它效率很低(因为点在绘制之前被复制到贝塞尔路径)。通过将我的数据切割成
我正在使用基于 SVM 分类的 HOG 特征检测器。我可以成功提取车牌,但提取的车牌除了车牌号外还有一些不必要的像素/线。我的图像处理流程如下: 在灰度图像上应用 HOG 检测器 裁剪检测到的区域 调
我有以下图片: 我想填充它的轮廓(即我想在这张图片中填充线条)。 我尝试了形态学闭合,但使用大小为 3x3 的矩形内核和 10 迭代并没有填满整个边界。我还尝试了一个 21x21 内核和 1 迭代,但
我必须找到一种算法,可以找到两组数组之间的交集总数,而其中一个数组已排序。 举个例子,我们有这两个数组,我们向相应的数字画直线。 这两个数组为我们提供了总共 7 个交集。 有什么样的算法可以帮助我解决
简单地说 - 我想使用透视投影从近裁剪平面绘制一条射线/线到远裁剪平面。我有我认为是使用各种 OpenGL/图形编程指南中描述的方法通过单击鼠标生成的正确标准化的世界坐标。 我遇到的问题是我的光线似乎
我是一名优秀的程序员,十分优秀!