我需要在GtkSourceView中打开文件并滚动到特定行。作为一个调试器gui,它需要频繁地执行此活动(当切换堆栈帧时),而不会出现短暂的伪影——内容的可见重新调整和闪烁。目前,我正在使用以下方法:
from gi.repository import GtkSource
class MyClientWindow:
def __init__(self):
self.__sourceview = GtkSource.View()
self.__sourceview.connect('size-allocate', self.__source_resize)
...
def __source_resize(self, widget, allocation):
self.__sourceview.scroll_to_mark(self.__sourceview.get_buffer().get_insert(), 0.25, False, 0, 0)
采用这种方法会出现可见的闪烁。将1s睡眠置于上面的__source_resize中表明,GtkSourceView在几次过程中得到了重新调整(在源高亮显示之前和之后明显绘制,以及一些额外的验证。)
有没有另一种方法可以强制GtkSource.View在不在屏幕上绘图的情况下计算线高度并执行验证,或者在我设置缓冲区内容时强制它立即计算线高度,而不将其推迟到以后的空闲作业?如果不是,我大概需要覆盖多少GtkSource.View控件才能获得所需的行为?
注意:我尝试使用Gtk.Stack在不可见的"后"视图中完成工作,并在稍后使用Gtk.idle_add使其可见,但我得到的印象是视图的可见性是行验证的关键。至少到目前为止,它没有提供所需的结果。
Gtk.Stack方法有效。它需要特定的操作顺序。这是我现在拥有的解决方案的摘录(为了清晰起见进行了修改):
class MyClientWindow:
def __init__(self):
self.__stack = Gtk.Stack()
...
def __switch_doc(content, line):
buffer = GtkSource.Buffer()
buffer.set_text(content)
# buffer style settings are applied here
...
iter = buffer.get_iter_at_line(line)
buffer.place_cursor(iter)
source_view = GtkSource.View.new_with_buffer(buffer)
prev_sw = self.__stack.get_visible_child()
next_sw = Gtk.ScrolledWindow()
next_sw.add(source_view)
next_sw.show_all()
self.__stack.add(next_sw)
GObject.idle_add(lambda: self.__switch_view(prev_sw, next_sw))
def __switch_view(self, prev_sw, next_sw):
source_view = next_sw.get_child()
buffer = source_view.get_buffer()
source_view.scroll_to_iter(buffer.get_iter_at_mark(buffer.get_insert()), 0, True, 0, 0.5)
if prev_sw:
self.__stack.remove(prev_sw)
我每次都重新创建GtkSourceView和父GtkScrollWindow。这可以在一定程度上进行优化(通过保留堆栈中的旧视图而不是删除它们。)
在将GtkScrollWindow添加到堆栈容器之前,显示它是非常重要的。否则,如果使用scroll_to_ter移动到文本中的新位置,则稍后显示时将缺少颜色。(我不知道这是不是一个错误。)
在添加小部件之前显示它会使它成为堆栈的"可见子",但只有在get_visible_child方法返回它的意义上。但是,它不会将其渲染到屏幕上。
删除旧的子项(或使用set_visible_child方法激活新的子项)时,图形开始,由于使用了idle_add,这发生在GtkSourceView的行验证之后。因此,可以使用scroll_to_iter而不是scroll_to_mark来执行滚动,这将进一步推迟动作。