Gtk + 3 - 在TextView中编写和自动滚动问题

时间:2012-01-10 12:09:26

标签: python multithreading gtk pygobject

我在Gtk.ScrolledWindow()内有一个Gtk.TextView(),(我正在使用PyGObject内省)。

在我插入一些文本并从另一个线程自动滚动后,连续多次调用方法append_text,我收到几个警告,然后GUI崩溃。

这是我的代码中的麻烦部分:

class TextViewWindow(Gtk.Window):

    [...]

    def append_text(self, text):
        self.textbuffer.insert(self.textbuffer.get_end_iter(), text)
        self.scroll_to_end()

    def scroll_to_end(self):
        self.textbuffer.place_cursor(self.textbuffer.get_end_iter())
        insert_mark = self.textbuffer.get_insert()
        self.textview.scroll_to_mark(insert_mark , 0.0, True, 0.0, 1.0)

有谁知道我做错了什么?

-
以下是我得到的一些错误:

  

Gtk-WARNING **:无效的文本缓冲区迭代器:迭代器未初始化,或者自迭代器创建以来缓冲区中的字符/ pixbufs / widgets已被修改。   必须使用标记,字符编号或行号来保留缓冲区修改的位置。   您可以应用标签并插入标记而不会使迭代器失效,   但是任何影响'可索引'缓冲区内容的变异(可以通过字符偏移引用的内容)   将使所有未完成的迭代器无效

     

Pango-CRITICAL **:pango_layout_index_to_pos:断言`layout!= NULL'失败

     

Gtk-WARNING **:gtktextview.c:4813:自上次验证屏幕上的行以来,某些文本行被修改或滚动 - 可能是文本小部件错误。

     

Gtk:错误:gtktextview.c:4814:gtk_text_view_paint:代码不应该到达

2 个答案:

答案 0 :(得分:2)

要更新Gtk widgets from other threads,您需要:

一个。在调用Gtk.main() 之前,请先调用以下方法

GObject.threads_init()
Gdk.threads_init()

湾在您的主题中,使用以下代码包围更新Gtk小部件的代码:

Gdk.threads_enter()
# your code here
Gdk.threads_leave()

在您的情况下,您可能需要以下内容:

Gdk.threads_enter()
your_window.append_text('something')
your_window.scroll_to_end()
Gdk.threads_leave()

答案 1 :(得分:1)

如果您正在使用线程,就像您的评论中所看到的那样,根据我的经验,尝试更新线程中的小部件效果不佳。

此问题的解决方法是使用GLib.idle_add计划更新窗口小部件的所有操作,以便在主线程中进行更新。