Re: where is it safe to redraw screens?




On Aug 5, 2006, at 10:34 AM, Dirk Koopman wrote:

It is safe simply to replace the current screen widget with the next
one, in the main window widget, whilst in the signal callback of the
"book on" buttons?

It should be. The widgets won't actually be destroyed until all references are released, and things pretty much just work. The widgets are allocated in the heap, so you don't have to worry about them being destroyed when their allocating scope goes away.

If you're really worried about it, you can have the buttons' callback install idle handlers to do the screen replacement, to guarantee that the screen replacement happens from the main loop.

Here's a very silly example of doing it both ways:

#!/usr/bin/perl -w
use strict;
use Gtk2 -init;

my $window = Gtk2::Window->new;
$window->add (make_frame_one ());
$window->show_all;
$window->signal_connect (destroy => sub {Gtk2->main_quit});
Gtk2->main;

sub make_frame_one {
        my $frame = Gtk2::Frame->new ("Screen One");
        my $vbox = Gtk2::VBox->new;
my $label = Gtk2::Label->new ("Click the shiny, red, candylike button to replace us all");
        my $button = Gtk2::Button->new ("The shiny, red, candylike button");
        # Wankery, pay it no mind.
        $button->modify_bg (normal => Gtk2::Gdk::Color->new (65535, 0, 0));
$button->modify_bg (prelight => Gtk2::Gdk::Color->new (65535, 32767, 32767));
        $vbox->add ($label);
        $vbox->add ($button);
        $frame->add ($vbox);
        $button->signal_connect (clicked => sub {
                # Be careful not to keep a reference to the old child in this
                # closure, or you'll get a reference cycle that will result
                # in badness.  This is less of a problem with named subs.
                # You can also do this destroy on one line, like
                #$window->get_child->destroy;
                my $oldframe = $window->get_child;
                $oldframe->destroy;
                $oldframe = undef; # release our local reference!
                my $newframe = make_frame_two();
                $window->add ($newframe);
                $newframe->show_all;
        });
        return $frame;
}

sub make_frame_two {
        my $frame = Gtk2::Frame->new ("Screen Two");
        my $vbox = Gtk2::VBox->new;
        my $label = Gtk2::Label->new ("This one is a lot less exciting.");
        my $button = Gtk2::Button->new ("Clicky");
        $vbox->add ($button);
        $vbox->add ($label);
        $frame->add ($vbox);
        $button->signal_connect (clicked => sub {
                # This time, we'll do the replacement from an idle handler
                # out of paranoia.
                Glib::Idle->add (sub {
                        $window->get_child->destroy;
                        my $newframe = make_frame_one();
                        $newframe->show_all;
                        $window->add ($newframe);
                        0; # don't run again
                });
        });
        return $frame;
}



A further, related, query: something like the fourth screen can appear
at anytime (there is a Gtk2::Helper->add_watch() listening on a socket
for incoming messages [which all works just fine]). A user may be
sitting in some modal "dialog" in a popup window. Can you just change
widget and it will redraw underneath or does one have to either destroy
or wait until the dialog window is closed, first?

That should be quite fine. Modal dialogs prevent user interaction with widgets underneath, but do not prevent them from actually working or responding to expose events. Here's a trivial proof:

#!/usr/bin/perl -w
use strict;
use Gtk2 -init;

my $window = Gtk2::Window->new;
my $treeview = Gtk2::TreeView->new;
$treeview->insert_column_with_attributes
        (-1, "Stuff", Gtk2::CellRendererText->new, text => 0);
my $scroller = Gtk2::ScrolledWindow->new;
$window->add ($scroller);
$scroller->add ($treeview);
$window->show_all;

my $model = Gtk2::ListStore->new ('Glib::Int');
$treeview->set_model ($model);

my $dialog = Gtk2::MessageDialog->new ($window, 'destroy-with-parent',
                                       'info', 'none', "Click to do stuff");
$dialog->add_buttons ('gtk-close' => 'close',
                      'gtk-run' => 'ok');

while ('close' ne $dialog->run) {
        # Cause stuff to happen in the parent window.
        $model->set ($model->append, 0, $model->iter_n_children(undef));
        $treeview->scroll_to_cell
                ($model->get_path
                        ($model->iter_nth_child
                                (undef, $model->iter_n_children(undef)-1)));
}

# Since the dialog is set for destroy-with-parent, this gets both of them.
$window->destroy;



--
To me, "hajime" means "the man standing opposite you is about to hit you with a stick".
  -- Ian Malpass, speaking of the Japanese word for "the beginning"




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]