in reply to Re: Unable To Keep Showing Last Item In Gtk2::TreeView
in thread Unable To Keep Showing Last Item In Gtk2::TreeView

Thanks for the suggestion. And, oops, on the Window/MainWindow thing. See the corrected version below, still with the shrink problem.

What you suggested is not quite what I'm after, since it unconditionally moves the scroll bar to the bottom of the view anytime a new item is added. I'm trying to move the scroll bar only if it is already at the bottom just before the new item is added. That way, I can be looking around somewhere else with the scroll bar, without it jumping to the bottom everytime another item is added.

So it's an annoyance issue: I want this auto-scrolling, but not while I'm looking somewhere else in the tree view. What I've got works, except when the tree view shrinks. That causes the scroll bar to move slightly off the bottom, mistakenly turning off auto-scrolling.

By the way, I've tried attaching to many different signals, but the tree view internals seem too stale for $tree->get_visible_range(), $tree->scroll_to_cell(), or whatever to work.

Still searching,

Jim

#!/usr/bin/perl use strict; use warnings; use Glib qw(TRUE FALSE); use Gtk2 -init; my($win,$tree)=createWin(); Glib::Timeout->add(1000,sub {tickCB($tree)}); $win->show_all(); Gtk2->main(); # # Creates the widgets in the application. Returns the main # window and tree view. # sub createWin { my($win,$scroll,$tree,$model); $win=new Gtk2::Window(); $win->set_default_size(250,300); $win->signal_connect(destroy => \&Gtk2::main_quit); $win->add($scroll=new Gtk2::ScrolledWindow()); $scroll->add($tree=new Gtk2::TreeView()); $tree->set_rules_hint(TRUE); $tree->insert_column_with_attributes(-1,'Goo', new Gtk2::CellRendererText(),text => 0); $tree->set_model($model= new Gtk2::ListStore('Glib::String')); addWord($model) for 0 .. 100; showLast($tree); return ($win,$tree); } # # Called at regular intervals to add another random "word" # to the bottom of the tree view. If the previous word was # visible beforehand, scrolls the tree view so the new word # is visible. # sub tickCB { my($tree)=@_; my($model)=$tree->get_model(); my($numRows)=$model->iter_n_children(undef); my($lastVis)=($tree->get_visible_range())[1]; my($mustScroll)=$lastVis && $lastVis->get_indices() == $numRows-1; addWord($model); showLast($tree) if $mustScroll; return TRUE; } # # Adds a random "word" to the bottom of the tree view. # sub addWord { my($model)=@_; my(@cons)=grep !/[aeiou]/,'a' .. 'z'; $model->set($model->append(),0, $cons[rand @cons] . 'oo'); } # # Scrolls the tree view so the last row is visible. # sub showLast { my($tree)=@_; my($numRows)=$tree->get_model()->iter_n_children(undef); $tree->scroll_to_cell( new Gtk2::TreePath($numRows-1),undef,TRUE,0.0,1.0); }

Replies are listed 'Best First'.
Re^3: Unable To Keep Showing Last Item In Gtk2::TreeView
by zentara (Cardinal) on Apr 09, 2012 at 20:24 UTC
Re^3: Unable To Keep Showing Last Item In Gtk2::TreeView
by zentara (Cardinal) on Apr 09, 2012 at 21:12 UTC
    Hi again, this is about as far as I got experimenting with maintaining scroll position. This script isn't considered bullet proof, it has a runaway condition if you click too fast on the zoom control, and not all the Labels work as intended. You might get some experience with Adjustments by playing with it. It also is on a Goo canvas, not a TreeView.:-)

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh

      I posted this question to gtk-perl, and was able to get something that appears to do what I want. To summarize, I found the right signals to watch for to keep the scroll bar at the bottom, unless the user moves it. It reacts correctly when items are added to the tree view, and when the window height shrinks.

      I include my final version below for reference. Thanks for the help.

      Jim

      #!/usr/bin/perl use strict; use warnings; use Glib qw(TRUE FALSE); use Gtk2 -init; my($numAdded)=0; my($win,$tree)=createWin(); Glib::Timeout->add(1000,sub {tickCB($tree)}); $win->show_all(); Gtk2->main(); # # Creates the widgets in the application. Returns the main # window and tree view. # sub createWin { my($win,$scroll,$tree,$model,$mustScroll); $win=new Gtk2::Window(); $win->set_default_size(250,300); $win->signal_connect(destroy => \&Gtk2::main_quit); $win->add($scroll=new Gtk2::ScrolledWindow()); $scroll->add($tree=new Gtk2::TreeView()); $tree->set_rules_hint(TRUE); $tree->insert_column_with_attributes(-1,'Goo', new Gtk2::CellRendererText(),text => 0); $tree->set_model($model= new Gtk2::ListStore('Glib::String')); $tree->signal_connect( size_allocate => sub {sizeCB(\$mustScroll,@_)}); $model->signal_connect( row_inserted => sub {rowCB(\$mustScroll,$tree,@_)}); $scroll->get_vadjustment()->signal_connect( value_changed => sub {$numAdded=0}); addWords($model,100); showLast($tree,\$mustScroll); return ($win,$tree); } # # Called at regular intervals to add more random "words" to # the bottom of the tree view. If the previous word was # visible beforehand, scrolls the tree view so the new # words are visible. # sub tickCB { my($tree)=@_; addWords($tree->get_model(),100); return TRUE; } # # Adds random "words" to the bottom of the tree view. # sub addWords { my($model,$numAdd)=@_; my(@cons)=grep !/[aeiou]/,'a' .. 'z'; for (1 .. $numAdd) { $model->set($model->append(),0, $cons[rand @cons] . 'oo'); $numAdded++; } } # # Scrolls the tree view so the last row is visible. # sub showLast { my($tree,$mustScroll)=@_; my($numRows)=$tree->get_model()->iter_n_children(undef); $tree->scroll_to_cell( new Gtk2::TreePath($numRows-1),undef,TRUE,0.0,1.0); $$mustScroll=TRUE; $numAdded=0; } # # Called each time the tree view is resized. This is where # we correct the scroll bar, moving it to the bottom if # appropriate. # sub sizeCB { my($mustScroll,$tree,$rect)=@_; showLast($tree,$mustScroll) if $$mustScroll; } # # Called each time a row is added to the model. # sub rowCB { my($mustScroll,$tree,$model,$path,$it)=@_; my($numRows)=$model->iter_n_children(undef); my($lastVis); if ($tree->realized()) { $lastVis=($tree->get_visible_range())[1]; $$mustScroll=$lastVis && $lastVis->get_indices() == $numRows-2-$numAdded; } else { $$mustScroll=TRUE; } }
        Beautiful! Thanks for posting that, I'm sure someone in the future will be looking for your technique. :-)

        I'm not really a human, but I play one on earth.
        Old Perl Programmer Haiku ................... flash japh