Re: Emitting a signal leads to a failed assertion




On Nov 3, 2007, at 5:26 AM, Ari Jolma wrote:

muppet kirjoitti:

On Nov 2, 2007, at 9:37 AM, Ari Jolma wrote:

GLib-GObject-CRITICAL **: g_object_notify: assertion `G_IS_OBJECT
(object)' failed


 (gdb) run myscript --g-fatal-warnings otherargs...
 (gdb) backtrace

sadly, the result is "no stack"

Blah.  No debugging symbols, i presume?


However, you don't want to connect directly to the ScrolledWindow's
scrollbar, anyway.  The scrollbars are combination
view-and-controllers.  The horizontal and vertical adjustments are
what you actually want. ScrolledWindow communicates with the scrollee through the adjustments; you can programatically control the scrolling
with the adjustments; etc, etc, etc.

How do I then react to the user scrolling?

By connecting to the value-changed signals on the vertical and horizontal adjustments. The user's manipulation of the scrollbars will cause the scrollbars to change the values in the adjustments, which will fire their value-changed signals.

To wit, this sample sets up a monitor on both adjustments, and includes a button to change the scrolling programmatically; you will see the monitor for both dragging the scrollbars and for clicking the "Center me" button.

-=-=-=-=-=-=-=-
#!/usr/bin/perl -w

use strict;
use Gtk2 -init;

open SELF, $0;
$/ = undef;
my $text = <SELF>;
close SELF;


# We'll supply our own adjustments to the scrolled window. You don't have
# to do this -- you can let ScrolledWindow create its own adjustments --
# but this will make it clearer that we own the adjustments and want to do # extra stuff to them. If you want, you can actually fetch the adjustments # on demand, but if you're going to connect to signals on them, you'll have # to watch the ScrolledWindow's adjustment properties' notify signals for
# changes.

# The values don't matter here, ScrolledWindow and TextView will mangle
# them to their liking.
my $vadj = Gtk2::Adjustment->new (0, 0, 1, 1, 1, 1);
my $hadj = Gtk2::Adjustment->new (0, 0, 1, 1, 1, 1);


# Watch all value changes on these guys.
$vadj->signal_connect (value_changed => sub {
        print "vertical scroll!  ".$_[0]->get_value()."\n";
});
$hadj->signal_connect (value_changed => sub {
        print "horizontal scroll!  ".$_[0]->get_value()."\n";
});


my $thing = Gtk2::TextView->new;
my $scrolled = Gtk2::ScrolledWindow->new ($hadj, $vadj);
$scrolled->set_policy ('always', 'always');
$scrolled->add ($thing);

my $buffer = $thing->get_buffer ();
$buffer->insert ($buffer->get_start_iter (), $text);

my $window = Gtk2::Window->new;
my $vbox = Gtk2::VBox->new;
$window->add ($vbox);
$vbox->add ($scrolled);

my $button = Gtk2::Button->new ("Center me");
$button->signal_connect (clicked => sub {
        # Change the scrolling programmatically.
$vadj->set_value (($vadj->upper - $vadj->lower - $vadj->page_size) / 2); $hadj->set_value (($hadj->upper - $hadj->lower - $vadj->page_size) / 2);
});

$vbox->pack_start ($button, 0, 0, 0);
# small, so it will most definitely scroll.
$window->set_default_size (200, 200);



$window->signal_connect (destroy => sub { Gtk2->main_quit });
$window->show_all ();
Gtk2->main ();
-=-=-=-=-=-=-=-

Now, an interesting thing is that the scroll adjustments in a general widget can change during its lifetime. When ScrolledWindow takes a scrollable widget under its wings, it tells that child, "here, use *these* adjustment objects", supplying objects of its own. When you're implementing something scrollable, you have to have pedantic code in your set-scroll-adjustments implementation that disconnects signals from the old and connects signals to the new objects.

ScrolledWindow, which you are subclassing, allows the user of the object to supply the adjustments at creation, and from my reading of gtk+/gtk/gtkscrolledwindow.c, at any time during the widget's lifetime. If you want to be pedantic, you'll have to watch notify::hadjustment and notify::vadjustment on the ScrolledWindow and update all your signals accordingly. HOWEVER, that's really rare -- about the only time you really have to deal with that is on object creation.


That sounds scary and complicated, but it really isn't. If you lay your code out with this in mind, it becomes trivial; otherwise, it can be quite painful.



I realized that the heart of the problem is here. In the render method,
I redraw the image and set the adjustments.

Ack! That sounds like your problem. Don't *set* the adjustments, *change* the adjustments.



For some reason I seem to be
unable to do it simply:

$self->set_vadjustment(...)

instead I have to (can't make it work other way):

$self->{old_hadj} = $self->get_hscrollbar->get_adjustment; # prevents a
warning
$self->get_hscrollbar->set_adjustment(...)

i.e. I have to store a reference to the adjustment, otherwise I get
critical error as above. The critical error is 'GTK_IS_ADJUSTMENT
failed', though

Likely because there are signals still attached to what you're storing in old_hadj, and if you don't store it there, it will be destroyed.


To give more concrete advice, i really need to have a better idea of how your stuff is actually laid out. Otherwise i'll just be guessing and saying things that only deepen the confusion. If you can't distill the program enough for a simple post, then contact me off-list.


--
I hate to break it to you, but magic data pixies don't exist.
  -- Simon Cozens





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