The fact is that you can't access the GUI from more than one thread,
usually the main thread. It's not enough to serialize your code; you
should be mutexed with the main thread queue. Search in this list for
multithreading, and you'll see the topic discussed in detail.
Regards,
Leandro.
DESCOMBES Thierry wrote:
Hello,
I'm using gtkmm-2.4.2.
I have several POSIX threads trying to insert text into a Textview. So,
I use a POSIX mutex to be sure that text is inserted into the
TextBuffer one after the other.
Most of time, it works but sometimes, I get some GTK error message :
(TTdaq Application v0.8b:16046): Gtk-WARNING **: Invalid text buffer
iterator: either the iterator is uninitialized, or the
characters/pixbufs/widgets in the buffer have been modified since the
iterator was created.
You must use marks, character numbers, or line numbers to preserve a
position across buffer modifications.
You can apply tags and insert marks without invalidating your iterators,
but any mutation that affects 'indexable' buffer contents (contents
that can be referred to by character offset)
will invalidate all outstanding iterators
(TTdaq Application v0.8b:16419): Gtk-CRITICAL **: file gtktextlayout.c:
line 813 (gtk_text_layout_real_invalidate): assertion
`layout->wrap_loop_count == 0' failed
(TTdaq Application v0.8b:18972): Gtk-CRITICAL **: file gtktextlayout.c:
line 813 (gtk_text_layout_real_invalidate): assertion
`layout->wrap_loop_count == 0' failed
(TTdaq Application v0.8b:18510): Gtk-CRITICAL **: file gtktextbuffer.c:
line 1810 (gtk_text_buffer_get_iter_at_mark): assertion
`!gtk_text_mark_get_deleted (mark)' failed
And sometimes... it crashes with a "Segmentation Fault".
I have already tried different implementation which doesn't work better
;-) !
One of them was to fill a std::queue and create a Glib thread for
re-read it, and insert the messages into the Textview (a kind of
producer/consummer)... But it crashes even more often !
Here is extracts of my application:
� enum LogType
� {
��� INFO,
��� WARNING,
��� ERROR
� };
� // This function is used by the different threads !
� void add(LogType l, std::string msg)
� {
��� pthread_mutex_lock(&pmut_log_update);
��� switch(l)
��� {
������ case INFO:
��� globalControlWidget->printInfoLog(msg);
��� break;
������ case WARNING:
��� globalControlWidget->printWarningLog(msg);
��� break;
������ case ERROR:
��� globalControlWidget->printErrorLog(msg);
��� break;
��� }
���
��� pthread_mutex_unlock(&pmut_log_update);�
� }
�
� ....
� /************************************************************/
� // The class GlobalControlWidget
�
� class GlobalControlWidget : public Gtk::VBox
� {
Gtk::TextView *logText;
Gtk::ScrolledWindow *logScrolledwindow;
Glib::RefPtr<Gtk::TextBuffer> refTextLogBuffer;
Glib::RefPtr<Gtk::TextBuffer::Tag> refTagError;
Glib::RefPtr<Gtk::TextBuffer::Tag> refTagWarning;
Glib::RefPtr<Gtk::TextBuffer::TagTable> refTagTable;
void scrollLogView();
��� public:
������� GlobalControlWidget(TTdaqMainWindow*);����
������� ~GlobalControlWidget();
void printInfoLog(const std::string &);
void printErrorLog(const std::string &);
void printWarningLog(const std::string &);
void updateStartStopBoutonsSensitivity();
� };
�
� GlobalControlWidget::GlobalControlWidget()
� {
�� logText = manage(new class Gtk::TextView());
�� logText->set_flags(Gtk::CAN_FOCUS);
�� logText->set_editable(false);
�� //refTextLogBuffer = Gtk::TextBuffer::create();
�� //logText->set_buffer(refTextLogBuffer);
�� refTextLogBuffer=logText->get_buffer();
�� refTextLogBuffer->signal_changed().connect( sigc::mem_fun(*this,
&GlobalControlWidget::scrollLogView));
�� //Create a TagTable:
�� refTagTable = refTextLogBuffer->get_tag_table();
�� //Apply color to some text.
�� //Create the tags:
�� refTagWarning = Gtk::TextBuffer::Tag::create("Warning_Message");
//We give it an arbitrary name.
�� refTagWarning->property_background() = "orange";
�� refTagTable->add(refTagWarning);
�� refTagError = Gtk::TextBuffer::Tag::create("Error_Message"); //We
give it an arbitrary name.
�� refTagError->property_background() = "red";
�� refTagTable->add(refTagError);
��
�� logScrolledwindow = manage(new class Gtk::ScrolledWindow());
�� logScrolledwindow->set_policy(Gtk::POLICY_NEVER,
Gtk::POLICY_ALWAYS);
�� logScrolledwindow->add(*logText);�
�� Gtk::Frame *logFrame = manage(new class Gtk::Frame("Log"));
�� logFrame->set_shadow_type(Gtk::SHADOW_ETCHED_IN);
�� logFrame->set_label_align(0,0);
�� logFrame->add(*logScrolledwindow);
��
�� pack_start(*logFrame, true, true, 5);
�� show_all_children();
�� show();
�� set_redraw_on_allocate(true);
� }
�
� void GlobalControlWidget::printInfoLog(const std::string &msg)
� {
��� refTextLogBuffer->insert(refTextLogBuffer->end(), msg+"\n");
� }
� void GlobalControlWidget::printErrorLog(const std::string &msg)
� {
��� refTextLogBuffer->insert_with_tag(refTextLogBuffer->end(),
msg+"\n", refTagError);
� }
� void GlobalControlWidget::printWarningLog(const std::string &msg)
� {
��� refTextLogBuffer->insert_with_tag(refTextLogBuffer->end(),
msg+"\n", refTagWarning);
� }
� void GlobalControlWidget::scrollLogView()
� {
��� logText->scroll_mark_onscreen( refTextLogBuffer->get_insert()
);
� }
�
Pleeaasse heelllpp !!!
Cheers,
DESCOMBES Thierry
_______________________________________________
gtkmm-list mailing list
gtkmm-list gnome org
http://mail.gnome.org/mailman/listinfo/gtkmm-list
|