Для прокрутки в GtkTextView вы должны использовать маркеры в GtkTextBuffer. Объекты GtkTextMark автоматически обновляются, поэтому просто создайте маркер один раз при создании TextBuffer.
- Создайте объект GtkTextBuffer и GtkTextMark
- Создайте GtkTextView
- Каждый раз, когда вы добавляете текст, вы можете вызвать gtk_text_view_scroll_to_mark , чтобы прокрутить в конце
Вот как это сделать:
C
GtkTextView *text_view;
GtkTextMark *text_mark_end;
void create_text_view () {
text_view = gtk_text_view_new ();
/* get the text buffer */
GtkTextBuffer *text_buffer;
text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
/* create an auto-updating 'always at end' marker to scroll */
GtkTextIter text_iter_end;
gtk_text_buffer_get_end_iter (text_buffer, &text_iter_end);
text_mark_end = gtk_text_buffer_create_mark (text_buffer,
NULL,
&text_iter_end,
FALSE);
}
void append_text(const gchar *text) {
if (text) {
/* get the text buffer */
GtkTextBuffer *text_buffer;
text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
/* get an end iter */
GtkTextIter text_iter_end;
gtk_text_buffer_get_end_iter (text_buffer, &text_iter_end);
/* append text */
gtk_text_buffer_insert (text_buffer, &text_iter_end);
/* now scroll to the end using marker */
gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (text_view),
text_mark_end,
0., FALSE, 0., 0.);
}
}
void destroy_text_view () {
g_object_unref (text_mark_end);
gtk_widget_destroy (text_view);
}
Python
#!/usr/bin/env python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
class TextView(Gtk.TextView):
def __init__(self):
Gtk.TextView.__init__(self)
# create mark for scrolling
text_buffer = self.get_buffer()
text_iter_end = text_buffer.get_end_iter()
self.text_mark_end = text_buffer.create_mark("", text_iter_end, False)
def append_text(self, text):
# append text
text_buffer = self.get_buffer()
text_iter_end = text_buffer.get_end_iter()
text_buffer.insert(text_iter_end, text)
# now scroll using mark
self.scroll_to_mark(self.text_mark_end, 0, False, 0, 0)
class Window(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self)
self.set_title('Test GtkTextView scrolling')
self.set_default_size(400, 300)
self.grid = Gtk.Grid()
self.scrolled_win = Gtk.ScrolledWindow()
self.text_view = TextView()
self.button = Gtk.Button(label='Append text')
self.scrolled_win.set_hexpand(True)
self.scrolled_win.set_vexpand(True)
self.scrolled_win.add(self.text_view)
self.grid.add(self.scrolled_win)
self.grid.add(self.button)
self.add(self.grid)
self.connect('destroy', Gtk.main_quit)
self.button.connect('clicked', self.on_button_clicked)
self.show_all()
def on_button_clicked(self, widget):
self.text_view.append_text('Hello\n' * 5);
if __name__ == '__main__':
win = Window()
Gtk.main()
Примечание:
Также имеется функция gtk_text_view_scroll_to_iter . Это не очень полезно, потому что GtkTextView использует анимированную прокрутку (анимированную прокрутку можно увидеть, например, с помощью gedit с PAGE вверх / вниз). В отличие от прокрутки на основе маркера, прокрутка на основе iter не очень хорошо работает с возможностью анимированной прокрутки GtkTextView:
https://developer.gnome.org/gtk3/stable/GtkTextView.html#gtk-text-view-scroll-to-iter
Обратите внимание, что эта функция использует вычисленные в настоящее времявысота строк в текстовом буфере. Высота строк вычисляется в обработчике бездействия;поэтому эта функция может не дать желаемого эффекта, если она вызывается до вычисления высоты. Чтобы избежать странностей, рассмотрите возможность использования gtk_text_view_scroll_to_mark (), которая сохраняет точку для прокрутки после проверки строки.