使用GtkTextBuffer

时间:2017-01-09 09:03:44

标签: c gtk

我正在开发一个基于Gtk的应用程序,我需要通过连接已经存在的文本,每隔X秒更新一次GtkTextBuffer。显然它成功但有时“随机”应用程序中止,我认为它是由于这个元素,因为它以前没有发生过。当有第二次/第三次更新时,它有时会中止(每次更新只添加一行),有时它根本不会中止。我已经将TextBuffer更新功能基于简单的聊天应用程序行为,但我不知道我做错了什么。更新功能是:

void updateTextWindow(char *new_msg){
    g_print("Msg rcv: %s\n", new_msg);
    GtkTextIter start, end;
    GtkTextBuffer *buffer = gtk_text_view_get_buffer (global_text_window);
    //global_text_window is a global gtkwidget where TextBuffer is embedded
    gchar *previous_text;

    gtk_text_buffer_get_bounds (buffer, &start, &end);
    previous_text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);

    strcat(previous_text, "\n");
    strcat(previous_text, new_msg);

    gtk_text_buffer_set_text(buffer, previous_text, -1);

    g_free(previous_text);
}

此外,声明和初始化所有GtkWidgets的main函数中的相关代码是:

void create_ui (CustomData *data) {

    [...]

    GtkWidget *secondary_box; /* for text entry & buffer */
    GtkScrolledWindow *scrolling_box;
    GtkWidget *text_window;
    GtkTextBuffer *buffer;
    GtkWidget *text_entry;

    secondary_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 1);
    gtk_widget_set_size_request(secondary_box, 600, -1);
    scrolling_box = gtk_scrolled_window_new(NULL, NULL);
    gtk_scrolled_window_set_policy(scrolling_box, GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
    text_entry = gtk_entry_new();
    global_text_entry = text_entry;
    gtk_entry_set_max_length(text_entry, 25);

    text_window = gtk_text_view_new();
    buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_window));
    gtk_text_buffer_set_text(buffer, "\n", -1);
    gtk_text_view_set_editable(text_window, FALSE);
    global_text_window = text_window;
    gtk_scrolled_window_add_with_viewport(scrolling_box, text_window);

    gtk_box_pack_end(GTK_CONTAINER(secondary_box), text_entry, FALSE, FALSE, 0);
    g_signal_connect(G_OBJECT(text_entry), "activate", G_CALLBACK(text_entry_cb), &data);
    gtk_box_pack_end(GTK_CONTAINER(secondary_box), scrolling_box, TRUE, TRUE, 0);

    [...]
}

更新函数是从另一个线程调用的,而不是来自文本输入小部件的“激活”回调。

感谢您的帮助

1 个答案:

答案 0 :(得分:2)

该代码没有意义。你正在连接成一个没有空间来容纳更多文本的字符串,这是等待发生的未定义行为!您发布的答案也没有意义,创建这样的文本副本毫无意义。这可能只是因为它使用了更多的堆,所以也许你会更幸运。仍然未定义的行为要连接到previous_text

如果要添加更多文本,则无需重新设置整个文本内容。只需使用gtk_text_buffer_insert()在最后插入新文本即可。首先使用gtk_text_buffer_get_iter_at_offset()获取缓冲区内容结尾的迭代器。

更新哦,而且,你绝对无法从多个线程调用GTK +。它不是一个线程安全的库,所以不要这样做。如果你这样做有点不清楚,但确实听起来像。