如何在GtkSource.View中的特定行打开文件而没有可见的闪烁?

时间:2015-11-17 10:14:29

标签: user-interface pygtk gtk3 gtksourceview

我需要在GtkSourceView中打开文件并滚动到特定行。作为各种调试器,它需要经常执行此活动(切换堆栈帧时),没有瞬态伪像 - 可见的内容重新调整和闪烁。目前,我使用以下方法:

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)

采用这种方法会出现明显的闪烁现象。在上面的__source_resize中放置1s睡眠显示GtkSourceView在几次传递中被重新调整(在源突出显示之前和之后可见地绘制,以及一些额外的验证。)

是否有另一种方法可以强制GtkSource.View计算线高并在不绘制屏幕的情况下执行验证,或强制它在我设置缓冲区内容时立即计算线高,而不会在以后将其推迟到空闲作业?如果没有,我需要覆盖多少GtkSource.View控件才能获得所需的行为?

注意:我尝试使用Gtk.Stack在隐藏的“后退”视图中完成工作,并在以后使用Gtk.idle_add使其可见,但我得到的印象是View的可见性是线验证的关键。至少到目前为止,它没有提供所需的结果。

1 个答案:

答案 0 :(得分:1)

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_iter移动到文本中的新位置,则稍后显示时将缺少着色。 (我无法确定这是否是一个错误。)

在添加窗口小部件之前显示窗口小部件使其成为堆栈的“可见子窗口”,但仅在意义上它是由get_visible_child方法返回的。但它不会将其呈现在屏幕上。

当旧的子节点被移除(或者使用set_visible_child方法激活新的子节点)时,绘图开始,这由于使用了上面的idle_add,在GtkSourceView的行验证之后发生。因此,可以使用scroll_to_iter而不是scroll_to_mark执行滚动,这将进一步推迟操作。