Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scroll to end of ScrolledWindow/TextView

Tags:

python

gtk

on a GTK3 program with Python I implemented a log. This is a TextView with TextBuffer in a ScrolledWindow. With a routine I append a new line to this log. Afterwards it should scroll to the last line.

def append_log(self, line):
    self.textbuffer.insert(self.textbuffer.get_end_iter(), "\n"+line, -1)
    # scrolling down

It should look like this: http://www.physik.tu-dresden.de/~s9472632/log_manual.png

But it doesn't work. I've tried the following code.

# 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)

Picture: http://www.physik.tu-dresden.de/~s9472632/log_scroll.png

It seems the last four arguments of scroll_to* (within_margin, use_align, xalign, yalign) do not have influence of the results.

How get it work?

Bye Markus

like image 906
Chickenmarkus Avatar asked Feb 08 '13 10:02

Chickenmarkus


1 Answers

So I think I know the problem. I think you've connected the wrong signal so that the TextView hasn't requested a new size yet. The code below uses the size-allocate signal of the TextView and it works like a charm.

#!/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()
like image 185
deinonychusaur Avatar answered Oct 02 '22 22:10

deinonychusaur