How to auto-scroll a gtk.scrolledwindow?
I have a treeview-widget inside a ScrolledWindow
, which is populated during runtime. I want the ScrolledWindow
to auto-scroll to the end of the list. I "solved" the problem, by adjusting the vadjustment
of the ScrolledWindow
, everytime a row is inserted into the treeview. e.g:
if new_line_in_row:
adj = self.scrolled开发者_Go百科_window.get_vadjustment()
adj.set_value( adj.upper - adj.page_size )
If i run the code in an interactive ipython session and set the value by myself, everything works as expected.
If i run the code with the default python interpreter, the auto-scroll doesn't work all the time. I debugged the code and the problem seems be, that the adjustment values have some kind of "lag" and are only changed after some period of time.
My question is: how do I scroll, reliably, to maximum position of the ScrolledWindow
? is a special signal generated which i can use? or is there a better way to set the adjustment-value
?
After widening my search-radius, i found a ruby-related answer. since the problem is gtk-related, it should be able to be solved in any language like this:
you connect the widget which changes, in my case the treeview, with gtk.widget
's 'size-allocate' signal and set the gtk.scrolledwindow
value to "upper - page_size". example:
self.treeview.connect('size-allocate', self.treeview_changed)
...
def treeview_changed(self, widget, event, data=None):
adj = self.scrolled_window.get_vadjustment()
adj.set_value( adj.upper - adj.page_size )
link to the original post at ruby-forum.com:
hint hint
fookatchu's answer can be improved so that the callback could be used by multiple widgets:
def treeview_changed( self, widget, event, data=None ):
adj = widget.get_vadjustment()
adj.set_value( adj.upper - adj.pagesize )
Python Gtk 3 version:
adj.set_value(adj.get_upper() - adj.get_page_size())
The accepted answer has helped me figure out a Rust solution in gtk-rs to the auto-scroll to end of content issue.
Here's a Rust snippet that might help others:
// Imports used for reference
use gtk::{TextBuffer, TextView, TextBufferBuilder, ScrolledWindow, ScrolledWindowBuilder};
// The text buffer where the text is appended later
let text_buffer: TextBuffer = TextBufferBuilder::new().build();
// The containing text view that holds the text buffer
let text_view: TextView = TextView::new_with_buffer(&text_buffer);
// The scrolled window container with fixed height/width that holds the text view
let scrolled_window: ScrolledWindow = ScrolledWindowBuilder::new()
.min_content_height(400)
.min_content_width(600)
.child(&text_view)
.build();
// Have the text view connect to signal "size-allocate"
text_view.connect_size_allocate(clone!(@weak scrolled_window => move |_,_| {
let adj = scrolled_window.get_vadjustment().unwrap();
adj.set_value(adj.get_upper() - adj.get_page_size());
}));
// ...
// Later on, fill buffer with some text.
text_buffer.insert(&mut text_buffer.get_end_iter(), "This is my text I'm adding");
None of the suggested solutions worked for me, but I was able to get the desired behavior doing this (using GTk4 bindings for Go):
adj := scrolledWindow.VAdjustment()
adj.SetUpper(adj.Upper() + adj.PageSize())
adj.SetValue(adj.Upper())
The other solutions would move the scrolled window (mine contained a list box) down to the 2nd-to-last item, but not show the last item. The way it was acting made me think that the upper limit needed to be increased, so I tried increasing it by page-size then setting the scroll value to the new upper limit.
Still need the callback (I used a textView rather than treeView):
textView = Gtk.TextView()
scrolledWindow = Gtk.ScrolledWindow()
def textViewChanged( self, widget ):
adjustment = scrolledWindow.get_vadjustment()
adjustment.set_value( adjustment.get_upper() - adjustment.get_page_size() )
textView.connect( "size-allocate", textViewChanged )
精彩评论