滚动到ScrolledWindow/TextView底部
在一个使用GTK3和Python的程序中,我实现了一个日志功能。这是一个带有文本缓冲区的文本视图,放在一个可滚动的窗口里。我有一个例程可以向这个日志中添加新的一行。之后,它应该自动滚动到最后一行。
def append_log(self, line):
self.textbuffer.insert(self.textbuffer.get_end_iter(), "\n"+line, -1)
# scrolling down
它应该看起来像这样:http://www.physik.tu-dresden.de/~s9472632/log_manual.png
但是它没有按预期工作。我尝试了以下代码。
# nothing happens
adj = self.scrolledwindow.get_vadjustment()
adj.set_value(adj.get_upper()-adj.get_page_size()) # same without subtraction (only upper or page_size)
self.scrolledwindow.set_vadjustment(adj) # with and without this line
.
# nothing happens
self.textview.scroll_to_iter(self.textbuffer.get_end_iter(), 0.0, False, 0.5, 0.5)
.
# works a bit but scroll bars cover the text (see picture below)
self.textview.scroll_to_mark(self.textbuffer.get_insert(), 0.0, False, 0.5, 0.5)
图片:http://www.physik.tu-dresden.de/~s9472632/log_scroll.png
看起来scroll_to*的最后四个参数(within_margin, use_align, xalign, yalign)对结果没有影响。
我该怎么做才能让它工作呢?
再见,Markus
3 个回答
3
对于 gtkmm 3.0 和 C++11:
void append(std::string s) {
textbuffer->insert(textbuffer->end(), s.c_str());
// Wait for Gui to Redraw with added line to buffer
while (gtk_events_pending())
gtk_main_iteration_do(false);
// Scoll to end of Buffer
auto it = textbuffer->get_iter_at_line(textbuffer->get_line_count());
TextView1.scroll_to(it);
}
5
我刚刚遇到这个问题,并且让scroll_to_mark这一行正常工作了。我觉得你的问题出在把'use_align'设置为False上。那一行应该是:
self.textview.scroll_to_mark(self.textbuffer.get_insert(), 0.0, True, 0.5, 0.5)
13
我想我知道问题出在哪了。你可能连接了错误的信号,导致 TextView
还没有请求新的大小。下面的代码使用了 TextView
的 size-allocate
信号,效果非常好。
#!/usr/bin/env python
from gi.repository import Gtk, GObject
class W(Gtk.Window):
def __init__(self):
super(W, self).__init__()
self.connect("destroy", Gtk.main_quit)
self.set_default_size(200, 400)
self._msg_i = 0
self._sw = Gtk.ScrolledWindow()
self.add(self._sw)
self._tw = Gtk.TextView()
self._tb = self._tw.get_buffer()
self._sw.add_with_viewport(self._tw)
#The signal should at least be connected after the scrolled window
#is created, since the callback works on it.
self._tw.connect("size-allocate", self._autoscroll)
GObject.timeout_add(400, self.sim_log) # Invokes spamming
self.show_all()
def sim_log(self, *args):
"""A simple spamming function to emulate some sort of logging"""
self._msg_i += 1
i = self._tb.get_end_iter()
self._tb.insert(i, "\n* Message {0} recieved!".format(self._msg_i), -1)
return True
def _autoscroll(self, *args):
"""The actual scrolling method"""
adj = self._sw.get_vadjustment()
adj.set_value(adj.get_upper() - adj.get_page_size())
if __name__ == "__main__":
w = W()
Gtk.main()