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

4 投票
2 回答
2533 浏览
提问于 2025-04-17 09:55

我有一个 Gtk.ScrolledWindow(),里面放了一个 Gtk.TextView(),(我在用 PyGObject 的反射功能)。

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

这是我代码中出问题的部分:

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 **: 无效的文本缓冲区迭代器:要么迭代器没有初始化,要么缓冲区中的字符/图像/小部件在迭代器创建后被修改了。你必须使用标记、字符编号或行编号来保持在缓冲区修改时的位置。你可以应用标签和插入标记而不使你的迭代器失效,但任何影响“可索引”缓冲区内容的修改(可以通过字符偏移量引用的内容)都会使所有未完成的迭代器失效。

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

Gtk-WARNING **: gtktextview.c:4813: 不知怎么的,自上次验证屏幕上的行以来,一些文本行被修改了或发生了滚动 - 这可能是文本小部件的一个错误。

Gtk:ERROR:gtktextview.c:4814:gtk_text_view_paint: 不应该到达的代码

2 个回答

1

如果你在使用线程,从你的评论来看是这样的,根据我的经验,在线程中尝试更新界面上的小部件(比如按钮、标签等)通常效果不好。

解决这个问题的一个方法是使用 GLib.idle_add 来安排所有更新小部件的操作,这样更新就会在主线程中进行。

3

要从其他线程更新 Gtk 小部件,你需要:

a. 在你调用 Gtk.main() 之前,先调用以下方法:

GObject.threads_init()
Gdk.threads_init()

b. 在你的线程中,把更新 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()

撰写回答