2017-01-09 5 views
0

Ich entwickle eine Gtk-basierte Anwendung, wo ich alle X Sekunden ein GtkTextBuffer aktualisieren muss, indem Sie den bereits vorhandenen Text verketten. Scheinbar gelingt es aber manchmal "zufällig" bricht die Anwendung ab und ich nehme an, dass es an diesem Element liegt, da es vorher nicht passiert ist. Es wird manchmal abgebrochen, wenn ein zweites/drittes Update durchgeführt wird (jedes Update fügt nur eine neue Zeile hinzu) und manchmal bricht es überhaupt nicht ab. Ich habe die TextBuffer-Update-Funktion auf einfache Chat-Anwendungen Verhalten, aber ich weiß nicht, was ich falsch mache. Die Update-Funktion ist:Unerwarteter Abbruch mit GtkTextBuffer

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); 
} 

Darüber hinaus ist der zugehörige Code in der Hauptfunktion, in der alle GtkWidgets deklarieren und initializated ist:

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); 

    [...] 
} 

Die Update-Funktion von einem anderen Thread aufgerufen wird, nicht von der „activate "Rückruf für das Texteingabe-Widget.

Vielen Dank für Ihre Hilfe

Antwort

2

Dieser Code macht keinen Sinn. Sie verketten sich zu einem String, der keinen Platz für mehr Text hat, das ist ein nicht definiertes Verhalten, das darauf wartet, dass es passiert! Ihre gepostete Antwort macht auch keinen Sinn, es macht keinen Sinn, eine Kopie des Textes zu erstellen. Das könnte helfen, nur weil es den Haufen ein bisschen mehr benutzt, also vielleicht hast du mehr Glück. Noch nicht definiertes Verhalten zum Verketten in previous_text.

Wenn Sie mehr Text anhängen möchten, müssen Sie nicht den gesamten Textinhalt neu festlegen. Verwenden Sie einfach gtk_text_buffer_insert(), um neuen Text am Ende einzufügen. Verwenden Sie zuerst gtk_text_buffer_get_iter_at_offset(), um einen Iterator für das Ende des Inhalts des Puffers zu erhalten.

UPDATE Oh, und auch, Sie absolut kann nicht Anruf GTK + von mehreren Threads. Es ist keine thread-sichere Bibliothek, also tu das nicht. Es ist ein bisschen unklar, wenn Sie das tun, aber es klingt sicher so.

+2

Sie haben vergessen, über den anderen Teil des Grundes zu sprechen, warum der Code abstürzt: GTK + ist nicht Thread-sicher; Alle Anpassungen am GtkTextBuffer müssen im Hauptthread vorgenommen werden, wobei 'gdk_threads_add_idle() 'zum Planen von Haupt-Thread-Aktionen verwendet wird. – andlabs

+0

@andlabs Danke, behoben. – unwind