Re: Again: creating new widgets




On Jan 30, 2007, at 2:50 PM, Peter Daum wrote:

I am trying to figure out, how to create new widgets ("real" widgets
with own signals) by composing or extending existing Gtk2 widgets.

I read the Glib::Object::Subclass man page and the previous discussion
on this list but I still quite get it.

There's a comparison of the traditional perl subclassing method and Glib::Object subclassing method on the website, http://gtk2- perl.sourceforge.net/doc/subclassing_widgets_in_perl.html .

The basic point is that you can't mix the two methods, as you have done in the code you posted.


I tried a very simple exapmple -
A time widget consisting of 2 spinbuttons put into a hbox:

use base qw(Gtk2::HBox);
use Glib::Object::Subclass

Problem number one --- use *either* base *or* Glib::Object::Subclass --- not both. Glib::Object::Subclass is a pragmatic module that will register a GType for you, which sets up the @ISA entry.


  'Gtk2::HBox',
  signals => {
              wrapped => { }
             };

sub minute_wrap {
    my ($sb_min,$sb_hour)= _;
    $sb_hour->spin($sb_min->get_value() ? 'GTK_SPIN_STEP_BACKWARD'
                                        : 'GTK_SPIN_STEP_FORWARD', 1);
}

Problem number two:

sub new {
    my $class=shift;
    my $hbox   = new Gtk2::HBox(1,5);
[snip setup code]
    bless $hbox, $class;
    return $hbox;
}

The call to Gtk2::HBox::new() calls gtk_hbox_new() under the hood, which calls g_object_new() with GTK_TYPE_HBOX. It creates an HBox, and will never create another type. Reblessing the instance after it has been created will allow perl to look up your minute_wrap() method, but the underlying widget will still be seen by gtk+ as a GTK_TYPE_HBOX, so it won't have the new signal you registered.

In general, if you use Glib::Object::Subclass, you typically should not implement a new(), because a suitable new will be inherited. The setup code you had in new() above should go into a sub named exactly INIT_INSTANCE, which will be called by perl as part of the process of instantiating your object.

    sub INIT_INSTANCE {
        my $self = shift;  # this is the object being constructed

        # if you want to simulate "new Gtk2::HBox(1,5)" here, you can
        # use HBox's properties to do that.
        $self->set (homogeneous => TRUE,
                    spacing => 5);

        # most of the setup code would go here, initializing
        # child widgets, etc.  Do everything *but* show() $self.
        my $sb_hour= new Gtk2::SpinButton(
                         new Gtk2::Adjustment(0,0,23,1,1,1), 1,0);
        my $sb_minute= new Gtk2::SpinButton(
                           new Gtk2::Adjustment(0,0,59,1,10,10), 1,0);
        $sb_hour->set_wrap(1);
        $sb_minute->set_wrap(1);
        $sb_minute->signal_connect("wrapped", \&minute_wrap, $sb_hour);
        $sb_hour->signal_connect("wrapped", sub {
$self->signal_emit("wrapped") }, 0);
        $self->add($sb_hour);
        $self->add($sb_minute);
    }

Hope that helps...


--
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]