Gtk2-Perl Home Page

Index

Contents

  1. General Information
    1. What is Gtk2-Perl?
    2. What are those acronyms (gtk, gtk+, Gtk-Perl, Gtk2-Perl, gtk2-perl-xs, ...) anyway?
    3. Is there a Gtk2-Perl mailing list?
    4. Is there a gtk+ (C) F.A.Q
    5. Is there a Gtk2-Perl IRC channel?
  2. Downloading, Building, Installing Gtk2-Perl
    1. Where can i get the latest releases of Gtk2-Perl?
    2. What do i need to run Gtk2-Perl applications?
    3. Are there Pre-built Packages available?
    4. Can i get Gtk2-Perl for Microsoft Windows?
    5. How do I obtain the current, unreleased, code of Gtk2-Perl?
    6. Everything hangs at Gtk2->init or Gtk2 '-init' / What's up 'make test' just stops as soon as it starts
    7. Why "make test" sometimes fails?
    8. Help! FreeBSD wants to use Perl 5.6, but the Gtk2 port needs 5.8! What do I do?
    9. Why sometimes Makefile.PL fails?
    10. What's a "sandbox"? - or - How can a keep from hosing my system?
    11. Where can i find the key with which the Gtk-Perl rpms are signed?
  3. Getting Started Developing with Gtk2-Perl
    1. Where can I find introductory documentation and tutorials for developing with Gtk2-Perl?
  4. Developing with Gtk2-Perl
    1. Why sometimes the UI does not update?
    2. How are enums and flags different from the C bindings?
    3. What's involved in porting from Gtk-Perl to Gtk2-Perl?
    4. How do you pass complex user data to signal callback?
    5. Where is g_object_unref / g_boxed_free / other resource deallocator? These documents tell me i must use them...
    6. How do i tell if two references point to the same object / widget?
    7. How do i keep data with an object?
    8. But what about g_object_get_data and g_object_set_data?
    9. I have this C pointer that i know points to a GObject/GtkWidget -- how can i get a Perl reference out of it?
    10. How do i get a GType?
    11. Okay then, how do i create string or integer columns in GtkTreeModels?
    12. Why does my timer / idle only run once or it doesn't seem to run at all?
    13. Do you have any tips for dealing with character encodings in perl, in relation to Gtk2-Perl?
    14. My app doesn't die when there's a problem in a signal callback, I just get some strange error message, what's up with that?
    15. Can I create an application that can run under both Gtk-Perl and Gtk2-Perl?
    16. I read that CList is deprecated, so what do i use?
    17. Can I use threads with Gtk2-Perl?
    18. How do I keep my GUI updating while doing a long file read?
    19. How do I set the color of a widget?
  5. Widget Specific Development Information
    1. What's up with the response values for Gtk2::Dialog?
    2. I need to use the pango constant PANGO_XXX_XXX where is it?
    3. Show me a simple example for Drag-n-Drop
    4. Nautilus to Gtk2 Drag-n-Drop
    5. How do I scroll to the bottom of a TextView?
    6. How do I set the background/foreground color of a Gtk2::CellRenderer?
  6. Developing Your Own Widgets with Gtk2-Perl
    1. How do I create a new widget as a subclass of an existing Gtk widget?
  7. Wrapping C Gtk+ Modules/Widgets in Gtk2-Perl
    1. I want to use the FooFrobnicator library with gtk2-perl, where are the perl bindings?
  8. Other Miscellaneous Questions
    1. Where's the Glade option to generate perl code?
    2. why aren't there any capitals letters, and why aren't the grammar correct in the documentation?
    3. What version supports the FooBar widget? Can i use Gtk2-Perl x.yy with gtk+ a.b.c?
    4. How do I know which version of Gtk2 and which version of Glib I am running ?

General Information

What is Gtk2-Perl?

Gtk2-Perl is the collective name for a set of Perl modules which provide language bindings for Gtk+ 2.x and various related libraries. These modules make it easy to write Gtk+ and Gnome applications using a natural, perlish, object-oriented syntax.

What are those acronyms (gtk, gtk+, Gtk-Perl, Gtk2-Perl, gtk2-perl-xs, ...) anyway?

gtk is the Gimp Tool Kit, whose proper name is GTK+. we generally use "gtk" to refer to the toolkit in general.

gtk+ is the GTK+ C library.

gtk-perl is/was the original perl binding project for GTK+, providing Perl access to versions 0.99 through 1.2 of GTK+.

gtk2-perl provides Perl access to the 2.x and 3.x series of GTK+ libraries. It is completely distinct from gtk-perl, due to the fact that gtk+ (the C library) went through major changes between 1.2 and 2.0. These changes mostly involve the separation of some of the base pieces of GTK+'s type system into libgobject, which is part of glib-2.x (in turn bound to Perl by the Glib module). Now, all Gtk2::Widgets are Glib::Objects.

gtk2-perl-xs refers to versions 0.20 and later of gtk2-perl. Versions up to 0.12 were based on the Inline module; in April of 2003, a complete rewrite, using perl's XS extension language directly, enabled gtk2-perl to get past some architectural hurdles imposed by Inline. When this code was put into the CVS respository, it went into the directory gtk2-perl-xs to differentiate it from the older code. The distinction is now unnecessary as the old versions are obselete.

Is there a Gtk2-Perl mailing list?

The list used by Gtk2-Perl, gtk-perl-list@gnome.org, is hosted by gnome the mailing list information page can be found at http://mail.gnome.org/mailman/listinfo/gtk-perl-list.

Is there a gtk+ (C) F.A.Q

The gtk+ F.A.Q: http://www.gtk.org/faq/. Much of what is found there will be helpful when developing with Gtk2-Perl.

Is there a Gtk2-Perl IRC channel?

Yes. #gtk-perl on irc.gnome.org is available for all your IRC needs. If the channel isn't open when you log in, just /join it and others are sure to come!

Downloading, Building, Installing Gtk2-Perl

Where can i get the latest releases of Gtk2-Perl?

The most recent releases of the Gtk2-Perl family of modules can be found at the official website of Gtk2-Perl at http://gtk2-perl.sourceforge.net/.

Marc Lehmann maintains Gtk2-Perl's modules on CPAN. Just search for Gtk2.

Gavin Brown maintains the Bundle::Gnome2 CPAN bundle. Installing this bundle module will also install all the currently available CPAN modules.

What do i need to run Gtk2-Perl applications?

The Glib, and Gtk modules are required and should be installed in that order. Optionally the Gnome2, Gnome2::Canvas, Gtk2::GladeXML, Gtk2::GtkSpell modules may be installed in any order, after Gtk2, if necessary or desired. Of course, you must have the corresponding libraries before you can install the perl modules which wrap them (e.g. Gtk2 requires gtk+-2.x, Gnome2 requires libgnomeui-2.x. etc).

If you are installing from source, you also need the ExtUtils::Depends module, in addition to a C compiler (of course), and the headers for all the required libraries (usually available via the 'devel' packages, e.g., glib-devel, gtk+-devel, etc, or by installing the libraries from source).

Are there Pre-built Packages available?

Yes.

Marc Brockschmidt maintains debian binaries for ix86, which are available as part of debian unstable.

Our own Ross McFarland uses mach to build binary and source RPMs directly from the specfiles in cvs for Red Hat 8.0, Red Hat 9, and Fedora Core 1 systems; these are available from our project page, usually within a day of the source release. http://sourceforge.net/project/showfiles.php?group_id=64773

Mandrake has their own set of RPMs -- if you're on Mandrake, be sure to use their packages or badness will ensue!

For you hapless Win32 users, there are two options:

If you know of binaries for some other platform, please let us know.

Can i get Gtk2-Perl for Microsoft Windows?

Yes, but building it is hairy. There are binaries available, see the FAQ entry about binaries. The easiest way to get gtk2-perl running on win32 may be to use Activestate perl and the native compiled binaries as described in the FAQ.

How do I obtain the current, unreleased, code of Gtk2-Perl?

Gtk2-Perl is hosted by sourceforge.net and therefore you may access the project cvs repositories through anonymous cvs. Information about doing so can be found at http://sourceforge.net/cvs/?group_id=64773.

NOTE: current development is happening in the directory gtk2-perl-xs.

Everything hangs at Gtk2->init or Gtk2 '-init' / What's up 'make test' just stops as soon as it starts

This has been reported, more than once, on the mailing list. The problem has been observed on debian systems, but there's no reason to think that it wouldn't happen on others.

As best as we can tell, which isn't very best, it is due to threading issues between Glib/Gtk and perl. There are three possible solutions all of which have been reported to work, separately, none of which are verified by the core Gtk2-Perl team, but come from reasonable sources. (that's a disclaimer, if you hose your system it's not our fault) Anyway the possible solutions are:

  • Compile the perl Glib module with --disable-threadsafe option passed when creating the Makefile from Makefile.PL.
  • Upgrade to the latest and greatest C Glib/Gtk+ packages.
  • Recompile perl with threads enabled.

For more detail on the subject poke around on, or send a message to, the mailing list, but hopefully one of the above should resolve things for you.

Why "make test" sometimes fails?

Sometimes, make test fails while trying to load ... _config.pm ...

Before version 0.20, gtk2-perl was based on the Inline module, and used a pm file for every widget and object; all of these routed through _config.pm or _blib_config.pm for some load-time magic. In the xs rewrite, we removed the hundred or so tiny pm files in favor of a single pm that boots a single shared object.

If you have an old inline-based build installed while attempting to test the modern xs-based code, you may get a clash; the tell-tale sign is usually perl-compile-time or missing symbol errors in files like Button.pm, Widget.pm, or _config.pm, which don't exist in the tree you've just built. Here's one of several examples posted to gtk-perl-list: http://mail.gnome.org/archives/gtk-perl-list/2003-August/msg00021.html

Unfortunately, versions before 0.20 and versions after 0.20 disagree about where in the library tree to install, so you can't really just install the new stuff over the old stuff. The only real solution is to manually delete the old pm and so files from your Perl library tree.

Help! FreeBSD wants to use Perl 5.6, but the Gtk2 port needs 5.8! What do I do?

What you want to do depends upon whether you have Perl installed already or not. If not, install the Perl 5.8 port from ports/lang/perl5.8, and then run 'use.perl port' (yes, even on 5.x). Then you can continue and everything should work well. If you have Perl 5.6.1 installed, first do a 'make build' in ports/lang/perl5.8, then stop any processes that need Perl. Next, deinstall Perl 5.6.1 and do a 'make install' in ports/lang/perl5.8. After this, do 'use.perl port' (yes, even on 5.x). It's recommended to use pkgdb -F and change all of the ports requiring Perl 5.6.1 to 5.8.2, and to use portupgrade -f 'p5-*' to upgrade all of the Perl ports to use 5.8.2 rather than 5.6.1.

contributed by apeiron

Why sometimes Makefile.PL fails?

Sometimes, perl Makefile.PL fails with something like:

*** can not find package gobject-2.0 >= 2.0.0
*** check that it is properly installed and available in PKG_CONFIG_PATH
  at Makefile.PL line 81

When running perl Makefile.PL the most common cause of error messages similar to the above are missing devel packages. The problem is that you need to have the glib/gtk+/etc. devel packages installed, those include the necessary header files and the pkg-config files for compliation.

If you are on debian, you can install the pre-requisite packages using the following

$ apt-get install libglib2.0-dev
$ apt-get install libgtk2.0-dev

What's a "sandbox"? - or - How can a keep from hosing my system?

There are times when you don't want to install a Perl module system-wide; perhaps you don't have write permission, or you don't want to hose your system, or you can't overwrite the distro's install because it will render other programs inoperable.

You want to use a sandbox.

A sandbox is a thing you play in when you're little, with the Tonka trucks and shovels and buckets, making sand castles that you can easily destroy and rebuild. With software, it's a directory tree separate from everything else in which you can install and run software, and then wipe it out and start over very easily.

How you'd set one up varies depending on your platform, but the key is using the PERL5LIB environment variable to control @INC without having to supply -I options to perl on every invocation.

Here's how i set up my sandbox to build and install gtk2-perl from sources:

  # choose a location for the sandbox
  export SANDBOX=$HOME/local

  # tell perl how to find stuff installed under that prefix.
  # NOTE the use of lib/perl5/site_perl !
  export PERL5LIB=$SANDBOX/lib/perl5/site_perl:$PERL5LIB

  # and an alias to reduce typing errors:
  alias do_makefile_pl='perl Makefile.PL PREFIX=$SANDBOX'

  # you probaby want to install other software to this sandbox,
  # as well.  we can do the same thing for regular libraries.
  export PATH=$SANDBOX/bin:$PATH
  export LD_LIBRARY_PATH=$SANDBOX/lib:$LD_LIBRARY_PATH
  export MANPATH=$SANDBOX/share/man:$MANPATH
  alias do_configure='./configure --prefix=$SANDBOX'

  # now we can build a bunch of modules...
  (cd ExtUtils-Depends && do_makefile_pl && make all test install)
  (cd ExtUtils-PkgConfig && do_makefile_pl && make all test install)
  (cd Glib && do_makefile_pl && make all test install)
  (cd Gtk2 && do_makefile_pl && make all test install)
  (cd Gnome2::Canvas && do_makefile_pl && make all test install)

  # and run scripts that use them.
  my_really_cool_gtk2perl_script

(Of course, if you've checked out the cvs tree, you can use the toplevel Makefile to build them all for you.)

If you've ever used JHBuild, you'll notice that this is similar to what you get if you do 'jhbuild shell'; the difference is that JHBuild doesn't set PERL5LIB for you.

Where can i find the key with which the Gtk-Perl rpms are signed?

The key currently being used belongs to Ross McFarland and can be found on mit's key server at: http://pgp.mit.edu:11371/pks/lookup?search=Ross+McFarland&op=index

Getting Started Developing with Gtk2-Perl

Where can I find introductory documentation and tutorials for developing with Gtk2-Perl?

If you're looking for a basic introduction of the fundamentals of developing with Gtk2-Perl then have a look at http://gtk2-perl.sourceforge.net/doc/intro/

The C Gtk2 tutorial at http://www.gtk.org/tutorial/ should with minimal effort and thought apply to Gtk2-Perl. See the above introduction and the Gtk2::api man page for more information on how to go about this.

The original Gtk-Perl tutorial can be found at http://personal.riverusers.com/~swilhelm/gtkperl-tutorial/, even though it is written for Gtk-Perl and now Gtk2-Perl much of its content will still apply.

A Gtk2-Perl study guide can be found here http://forgeftp.novell.com/gtk2-perl-study/homepage/index.html .Thanks to Dirk van der Walt.

Developing with Gtk2-Perl

Why sometimes the UI does not update?

GTK+ uses a main loop which polls the various event sources. In essense, when you write:

  Gtk2->main();

you enter inside the main loop, which looks like this:

  while there are sources ready
    if there are events pending
      process events
    if there are timeout sources
      execute timeouts
    if there are idle sources
      execute idles

If you add a  while(1) { ... }  loop in your code, the flow of you application will block inside your loop, preventing the main loop to spin and thus processing events, timeouts and idles. You should never, ever add such a loop in your code. Use timeout and idle sources (see Glib::Timeout->add() and Glib::Idle->add()) to check for a condition after a quantum of time or whenever possible without blocking the main loop. If you need to poll a file or a pipe, see the FAQ below about using Glib::IO->add_watch(). If you need to make heavy computations and you cannot break them into an idle source or a timeout you might want to consider threading; see the FAQ below for the typical gotchas about using threads in Gtk2 applications.

How are enums and flags different from the C bindings?

Take a look at http://gtk2-perl.sourceforge.net/doc/Gtk2::api.pod.html#flags_and_enums for the detailed version, but the simple answer for enums is that you use the unique portion of the name replacing _ with - in a string, so:

  /* Built-in stock icon sizes */
  typedef enum
  {
    GTK_ICON_SIZE_INVALID,        /* 'invalid'       */
    GTK_ICON_SIZE_MENU,           /* 'menu'          */
    GTK_ICON_SIZE_SMALL_TOOLBAR,  /* 'small-toolbar' */
    GTK_ICON_SIZE_LARGE_TOOLBAR,  /* 'large-toolbar' */
    GTK_ICON_SIZE_BUTTON,         /* 'button'        */
    GTK_ICON_SIZE_DND,            /* 'dnd'           */
    GTK_ICON_SIZE_DIALOG          /* 'dialog'        */
  } GtkIconSize;

Example:  $icon->set_from_stock('gtk-apply', 'large-toolbar'); 

The same applies to flags but since multiple flags can be passed the desired values are specified as an array of strings:

  /* priorities for path lookups */
  typedef enum
  {
    GTK_PATH_PRIO_LOWEST      = 0,  /* 'lowest'      */
    GTK_PATH_PRIO_GTK         = 4,  /* 'gtk'         */
    GTK_PATH_PRIO_APPLICATION = 8,  /* 'application' */
    GTK_PATH_PRIO_THEME       = 10, /* 'theme'       */
    GTK_PATH_PRIO_RC          = 12, /* 'rc'          */
    GTK_PATH_PRIO_HIGHEST     = 15  /* 'highest'     */
  } GtkPathPriorityType;

Example:  Gtk2->gtk_rc_parse_priority ($scanner, ['lowest', 'rc', 'gtk'] ); 

What's involved in porting from Gtk-Perl to Gtk2-Perl?

In most cases there are very few changes required when porting a Gtk-Perl application to Gtk2-Perl and almost all of those are a result of changes to Gtk itself. The most obvious change is that package names are now Gtk2 instead of Gtk. There were a few common widgets that underwent substantial changes: Gtk::Text, Gtk::CList, Gtk::CTree, Gtk::List, and Gtk::Tree. If you use any of those the porting will require more effort, but once you understand the new model, view, controller architecture it should be pretty striaghtforwad.

One other noteworthy difference would be that with Gtk2-Perl you may only connect one user data variable to a connected signal. See the FAQ entry 'How do you pass complex user data to signal callback?' for more information.

The Gtk documentation should provide you with all of the information necessary, starting with http://developer.gnome.org/doc/API/2.0/gtk/gtk-changes-2-0.html.

How do you pass complex user data to signal callback?

First off in most cases you should take advantage of perl closures which free you from the need to pass user data in the first place. Even better than that you don't have to do anything to use them:

  my $label = Gtk2::Lable->new('Initial string');
  my $button = Gtk2::Button->new;
  $button->signal_connect (clicked => sub {
                   # with this closure we get to label directly
                   # and thanks to the magic (ref counting) of perl we
                   #  don't have to worry about the label going away
                   $label->set_text('Clicked string');
      }, $user_data);

Ok so there are cases where the above example won't suffice, so read on to find out what to do then. In Gtk2-Perl, as with Gtk+, all signal connections can take only one user data variable, however with perl it is easy to get more complex object into the callback by using references to arrays or hashes. Consult your favorite Perl book or website for more information on references, what follows are examples of most of the ways complex user data can be passed into a callback.

  # basic 1 variable in
  $button->signal_connect (clicked => sub {
                my $btn = shift;
                my $udata = shift;
        }, $user_data);
  
  # two variables in via an inline array reference, 
  # caught as an array reference
  $button->signal_connect (clicked => sub {
                my $btn = shift;
                my $udata = shift;
                # $udata->[0], $udata->[1]
        }, [ $user_data1, $user_data2 ] );
  
  # two variables in via an inline array reference, 
  # caught as an array
  $button->signal_connect (clicked => sub {
                my $btn = shift;
                my @udata = @{shift(@_)};
        }, [ $user_data1, $user_data2 ] );
  
  # two variables in via an inline array reference, 
  # caught into seperate variables
  $button->signal_connect (clicked => sub {
                my $btn = shift;
                my ($udata1, $udata2) = @{shift(@_)};
        }, [ $user_data1, $user_data2 ] );
  
  # a hash passed in via an inline hash reference,
  # caught as a hash reference
  $button->signal_connect (clicked => sub {
                my $btn = shift;
                my $udata = shift;
                # $udata->{user_data1}, $udata->{user_data2}
        }, { 
                user_data1 => $user_data1,
                user_data2 => $user_data2,
        });
  
  # a hash passed in via an inline hash reference,
  # caught as a hash 
  $button->signal_connect (clicked => sub {
                my $btn = shift;
                my %udata = %{shift(@_)};
        }, { 
                user_data1 => $user_data1,
                user_data2 => $user_data2,
        });

  # an array passed in by taking a reference to an array
  # caught into an array
  my @array = ( $user_data1, $user_data2 );
  $button->signal_connect (clicked => sub {
                my $btn = shift;
                my @udata = @{shift(@_)};
        }, \@array);
  
  # a hash passed in by taking a reference to a hash,
  # caught as a hash 
  my %hash = (
        user_data1 => $user_data1,
        user_data2 => $user_data2,
  );
  $button->signal_connect (clicked => sub {
                my $btn = shift;
                my %udata = %{shift(@_)};
        }, \%hash);

Where is g_object_unref / g_boxed_free / other resource deallocator? These documents tell me i must use them...

C, since it is not inherently object oriented, makes you clean up after yourself pedantically, but with perl all of this is auto-magically handled for you. Fret not.

Wrinkle: versions of gtk2-perl < 0.20 required you to use ->destroy and ->unref; if you are using those versions, you should really consider upgrading.

How do i tell if two references point to the same object / widget?

Just like you do any other perl object. :-)

   $object1 == $object2
   $object1 != $object2

The GObject and Perl object are fused into a single magical unit. for details on how we did it, see the developer docs for Glib. from the perl developer's perspective, it just works like it should.

However, this does NOT hold true for boxed types, only for GObject derivatives.

How do i keep data with an object?

Glib::Object is just a blessed hash reference, like any typical Perl object. You can store anything you want in the hash, and it will stay alive as long as the object does. The C-level GObject is attached to it by magic (honest!), so there's no chance of you breaking the wrapper by overwriting a key in the hash.

But what about g_object_get_data and g_object_set_data?

What about them? They're still available, but since they only allow you to store a generic pointer value (in C), they are not typesafe, so the perl bindings have no way to determining what's in there. Thus, you can use $object->get_data (key) and $object->set_data (key,val), but only with unsigned integers. This gives them limited usefulness. Just use hash keys unless you really know what you're doing.

I have this C pointer that i know points to a GObject/GtkWidget -- how can i get a Perl reference out of it?

Are you absolutely sure it points to a GObject?

If so, Glib::Object->new_from_pointer (pointer) will return a perl object blessed into whatever perl package corresponds to G_OBJECT_TYPE (pointer) in C. If the bottommost class isn't known to gtk2-perl, the first known one is. This is a rudimentary way to work with foreign objects and libraries which don't have perl bindings. If you need more functionality, you need to look at the Binding How-to.

If you're not absolutely certain your integer value is a GObject pointer, then don't be surprised if you get a core dump. GObject does not provide any safe way of determining if a generic pointer is really an object -- one of the first things it does it dereference the pointer, and if it's not really a pointer, then you get nasty memory access errors which kill your program. In this sort of situation, you'd be better off writing a binding to be on the safe side.

How do i get a GType?

You don't. Use a Perl package name instead, as a string, e.g. "Glib::Object", "Gtk2::Button", etc.

Okay then, how do i create string or integer columns in GtkTreeModels?

Glib registers package names for some of the basic types:

  • Glib::String

  • Glib::Boolean

  • Glib::Int

  • Glib::Uint

  • Glib::Double

  • Glib::Scalar

'Glib::Scalar' is for generic perl scalars, including references. Perl has doubles natively, so Glib::Float is pointless; similarly for the other integer sizes.

Most of the stringified enum and flag types are registered as well, so you can create columns of enum types.

Why does my timer / idle only run once or it doesn't seem to run at all?

In some callbacks (idle and timeout being examples) the return type indicates whether you would like to be called again or removed. You have to return true to keep it installed. By returning nothing, you implicitly return false, which means "uninstall me".

Do you have any tips for dealing with character encodings in perl, in relation to Gtk2-Perl?

Gtk+ 2.0 and thus the Gtk2 modules use UTF-8 for encoding all of its strings. The Gtk2 modules will take care of converting the strings to and from Perls internal representation.

Probably the easiest way is to let Perl do the work for you. When reading from a file you can let a PerlIO layer convert from the files encoding to the internal representation of Perl. The "encoding" layer is provided by the core module Encode.

  # reading from a file encoded in iso-8859-15 (latin1 + Euro)
        use Encode;
        open my $in, "<:encoding(iso-8859-15)", $infile or die;
        while(<$in>) {
                # $_ is ready for use with Gtk2
                ...
        }
  
  # writing the to a iso-8859-15 encoded file
        use Encode;
        open my $out, ">:encoding(iso-8859-15)", $outfile or die;
        print $out, "...";

You can also use Encode to convert individual strings. Usually there should be no need to worry about that, but sometimes a module will return values that are not converted to Perls internal encoding. If that is the case "decode" can be used to convert to the internal representation.

        use Encode qw(decode encode);
        my $octets= broken_sub();
        my $string= decode("iso-8859-15", $octets); # ready for Gtk2
        my $label = Gtk2::Label->new($string);
        $string= $label->get_text;
        $octets= encode("iso-8859-15", $string);

- Christian Borup.

My app doesn't die when there's a problem in a signal callback, I just get some strange error message, what's up with that?

This is a long and thoroughly discussed topic (see the gtk-perl mailing list archives for some of it.) Basically it comes down to the fact that an application die'ing or croak'ing, explicitly or implicitly, in a signal callback and being caught somewhere outside of that callback is a very bad thing. Were this allow to happen stray main loops that could never be killed and other such badness could arrise. Just to be clear it is perfectly fine and acceptable to have the eval and catch all withing the signal callback, for example:

  $button->signal_connect (clicked => sub {
          eval { 
              do_something_that_might_croak_or_die();
              # or just
              die "a horrible death";
          }
          if( $@ )
          {
              # handle things here
          }
      } );

but not:

  $button->signal_connect (clicked => sub {
          die "a horrible death";
      } );
  # and try catching it somewhere else

Now that's out of the way I can provide you with a little information on the mechinism to catch/handle die's/croak's/errors in signal callbacks:

  Glib->install_exception_handler (sub {
          my $msg = shift;
          my $udata = shift;
          # msg = what used to be in $@
  }, $user_data);

It works much like connecting any other signal. When an exception occurs in a signal callback the function will be invoked and the error message will be passed in as the first paramter. You may then do whatever you desire with that piece of information. (See Glib's man page for more information.) Perhaps the most common use would be to get back to the old behavior of the application exiting on such errors:

  Glib->install_exception_handler (sub {
          warn shift;
          exit -1;
  });

This isn't the place to try to convince you of the details of this issue, so hopefully you will just accept that it is the case, if not then turn to the mailing list and discussion shall ensue.

Can I create an application that can run under both Gtk-Perl and Gtk2-Perl?

Well yes, in general, but it will take some non-trivial effort on your part. For a simple app it could be done, but anything real would be more work than it would be worth (of course this is an opinion.) An example of a script that would work under both would be:

  #!/usr/bin/perl -w
  
  my $gtk;
  
  if (eval "use Gtk2 -init; 1") {
          warn "Gtk2 is available";
          $gtk = 'Gtk2';
  } elsif (eval "use Gtk -init; 1") {
          warn "Gtk is available";
          $gtk = 'Gtk';
  } else {
          die "neither Gtk2 nor Gtk is available, can't run!\n";
  }
  
  
  my $window = "$gtk\::Window"->new ('toplevel');
  $window->signal_connect (delete_event => sub { $gtk->main_quit; 1 });
  my $vbox = "$gtk\::VBox"->new;
  $window->add ($vbox);
  $vbox->pack_start ("$gtk\::Label"->new ("using $gtk"), 0, 0, 0);
  my $button = "$gtk\::Button"->new ("Quit");
  $vbox->pack_start ($button, 0, 0, 0);
  $button->signal_connect (clicked => sub { $gtk->main_quit; });
  
  $window->show_all;
  
  $gtk->main;

To create an app that could truely function under both would require dealing with other mor complex issues such as those where a widget existed in Gtk, but has been replalced with another, completely different, widget in Gtk2. If you're undertaking such an endevor good luck.

I read that CList is deprecated, so what do i use?

CList was replaced in Gtk+ 2.0 with a MVC (Model View Controler or something like that,) for indepth coverage of the topic look here, http://developer.gnome.org/doc/API/2.0/gtk/TreeWidgetObjects.html.

You may also want to take a look at Gtk2::SimpleList, examples/simplelist.pl.

There are several examples of how to use the MVC stuff in the t (tests) directory as well as in the gtk-demo app of the perl module Gtk2.

Take a look at this thread from the gtk-perl mailing list for more info, well not really, but it's kinda funny: http://mail.gnome.org/archives/gtk-perl-list/2003-September/msg00209.html

Can I use threads with Gtk2-Perl?

Yes, if you are very careful.

In general, you want to mess with the gui from only one thread, and then you're safe. An extra wrinkle for gtk2-perl is that you need to create your extra threads before you create any gtk2-perl objects or widgets.

There are a few threads in the mailing list archives about this topic. This message, in particular, includes working code: http://mail.gnome.org/archives/gtk-perl-list/2003-November/msg00028.html

Because of this mess, it's usually best to avoid threads if you can. If you need to monitor a file or socket for input, use Glib::IO->add_watch to wait for events on that file descriptor. You can also spawn other programs and communicate via pipes, and even use Gtk2::Plugs and Gtk2::Sockets to put that child process' widgets into the parent's gui.

How do I keep my GUI updating while doing a long file read?

A rule of thumb in any event driven program is that you should never have to give up the main loop and do polling. It is only in very rare circumstance that you need to resort to such things. Instead you have to add to the event loop information that tells it to call your callback once there is something to read on a file handle.

This is explained in Gtk2::Helper. Here is my interpretation of it:

######################################################################
#  Example of howto use the Gtk2::Helper functions to get input from
#  a file descriptor.
######################################################################

use Gtk2 '-init';
use Gtk2::Helper;
use strict;

my $buffer;

sub create_widgets {
    my $wm   = Gtk2::Window->new;
    my $vbox = Gtk2::VBox->new;
    my $sw   = Gtk2::ScrolledWindow->new( undef, undef );
    my $tw   = Gtk2::TextView->new();
    $buffer = $tw->get_buffer();
    $wm->set_default_size( 400, 300 );
    $sw->add( $tw );
    $sw->set_policy( 'automatic', 'automatic' );
    $vbox->pack_start( $sw, 1, 1, 0 );

    my $button = Gtk2::Button->new( "Quit" );
    $vbox->pack_start( $button, 0, 0, 0 );
    $button->signal_connect( clicked => sub { exit } );
    $wm->add( $vbox );

    $wm->show_all();
}

create_widgets();

open my $pipe, '-|', perl => -e => '$|++; for my $i (0..9) { $sum+= $i; print "Line $i: sum = $sum\n"; sleep 1;}'
    or die "Failed running perl subprocess\n";

my $tag;

$tag = Gtk2::Helper->add_watch( fileno( $pipe ), in => sub {
    if ( eof( $pipe ) ) {
        Gtk2::Helper->remove_watch( $tag );
        close( $pipe );
    }
    else {
        my $line = <$pipe>;
        $buffer->insert( $buffer->get_end_iter, $line );
    }

    return 1;
} );

Gtk2->main;

The main lines are this bit:

open my $pipe, '-|', 'program', 'with', 'args'

and this:

$tag = Gtk2::Helper->add_watch( $fileno, 'in', sub {...} )

Helper->add_watch() call tells gtk to call the anonymous subroutine when there is something to read on the filehandle.

-- Dov Grobgeld

How do I set the color of a widget?

Havoc Pennington has written this up better than i can (see http://ometer.com/gtk-colors.html). You can translate his C syntax to Perl easily with the help of the Gtk2::api manpage. I will not provide that translation here, because you need to read the lecture on why you shouldn't do this.

Widget Specific Development Information

What's up with the response values for Gtk2::Dialog?

In C, GtkDialog's response codes are integers, with some predefined values provided by the GtkResponseType enumeration. The values provided by the enum are negative, and any positive number is considered to be application-specific.

In translating this to perl, we decided to have these codes represented as an enumerated type with unknown integer values passed through unadulterated. Thus, for stock gtk dialogs, you'll get response codes like 'delete-event', 'ok', or 'accept'. When creating dialog responses (i.e., adding buttons), you can use the enumeration values ('ok', 'cancel', etc) or you can use any integer (1, 42, 1138). since perl will stringfy numbers as necessary, it's easiest just to use eq for comparing the response ids, like this:

# adding a predefined response
$dialog->add_button ('gtk-ok' => 'ok');
# or a custom response
$dialog->add_button ('something' => 42);
  
# modally
if ('ok' eq $dialog->run) {
    # whatever
}
  
# or via the signal
$dialog->signal_connect (response => sub {
    my ($widget, $response) = @_;
    if ($response eq 'accept') {
        # was a predefined one
    } elsif ($response eq 42) {
        # was a custom one
    }
});

Note, however, that you can't use arbitrary strings as response codes, only the enum values and integers.

I need to use the pango constant PANGO_XXX_XXX where is it?

Several of the Pango constants are only discrete points on a continum of possible values and thus can't be represented as a enum type like most everything else in Gtk2. These constants do exist though, the can be loaded by adding the following line to your app:

use Gtk2::Pango;

The pango constants (see the Gtk2::Pango man pago for more information on what is avaiable and under what symbols.) can then be used in the function calls that may recieve them.

Show me a simple example for Drag-n-Drop

Try this out. You can drag and drop stuff between two 'lists' here. This one uses Gtk2::Ex::Simple::List. You can find a more complex example in the examples folder of the Gtk2-Perl package.

use Gtk2 '-init';
use Gtk2::Ex::Simple::List;
use Glib qw /TRUE FALSE/;

# Declare the lists
my $leftlist  = Gtk2::Ex::Simple::List->new ('Left'     => 'text',);
my $rightlist = Gtk2::Ex::Simple::List->new ('Right'=> 'text',);
$leftlist->get_selection->set_mode ('multiple');
$rightlist->get_selection->set_mode ('multiple');

# For dragging from left to right
$leftlist->drag_source_set (['button1_mask', 'button3_mask'],['copy', 'move'], 
        {'target' => "STRING", 'flags' => [], 'info' => 0});
$rightlist->drag_dest_set('all', ['copy', 'move'], 
        {'target' => "STRING", 'flags' => [], 'info' => 0});
$leftlist->signal_connect ('drag-data-get', \&source_drag_data_get);
$rightlist->signal_connect('drag-data-received', \&drag_data_received, $leftlist);

# For dragging from right to left (just the inverse)
$rightlist->drag_source_set (['button1_mask', 'button3_mask'], ['copy', 'move'], 
        {'target' => "STRING", 'flags' => [], 'info' => 0});
$leftlist->drag_dest_set('all', ['copy', 'move'], 
        {'target' => "STRING", 'flags' => [], 'info' => 0});
$rightlist->signal_connect ('drag-data-get', \&source_drag_data_get);
$leftlist->signal_connect('drag-data-received', \&drag_data_received, $rightlist);

# Populate the leftlist
@{$leftlist->{data}} = ('one', 'two', 'three', 'four', 'five', 'six', 'seven');

# Pack the widgets and display
my $hbox = Gtk2::HBox->new(FALSE);
$hbox->pack_start($leftlist, TRUE, TRUE, 0);
$hbox->pack_start($rightlist, TRUE, TRUE, 0);
my $window = Gtk2::Window->new;
$window->signal_connect(destroy => sub { Gtk2->main_quit; });
$window->add($hbox);
$window->set_default_size(400,350);
$window->show_all;
Gtk2->main;

sub source_drag_data_get {
        my ($widget, $context, $data, $info, $time) = @_;
        $data->set ($data->target, 0, 0);
}

sub drag_data_received {
        my ($tolist, $context, $x, $y, $data, $info, $time, $fromlist) = @_;
        my @selectedindices = $fromlist->get_selected_indices;
        _move_from_to ($fromlist, $tolist, \@selectedindices);
}

sub _move_from_to {
        my ($fromlist, $tolist, $selectedindices) = @_;
        # Populate the tolist
        foreach my $i (@$selectedindices) {
                push @{$tolist->{data}}, $fromlist->{data}->[$i];
        }
        my %hash = map { $_ => 1 } @$selectedindices;
        my @temp;
        # Remove entries from fromlist
        for my $i (0 .. $#{ @{$fromlist->{data}}) {
                push @temp, $fromlist->{data}->[$i]->[0] unless exists($hash{$i});
        }
        @{$fromlist->{data}} = @temp;   
}

-- Ofey

Nautilus to Gtk2 Drag-n-Drop

The magic lies in using the right target atom, which turned out to be "text/uri-list" and $data->data is a newline seperated list of URIs (probably beginning with file:// if they're local files)

  $widget->drag_dest_set(["drop","motion","highlight"],
                         ["copy","private","default","move","link","ask"]);
  $widget->signal_connect(drag_data_received => \&drop_handler);
  
  my $target_list = Gtk2::TargetList->new();
  my $atom = Gtk2::Gdk::Atom->new("text/uri-list");
  $target_list->add($atom, 0, 0);
  $widget->drag_dest_set_target_list($target_list);
  
  sub drop_handler {
    my ($treeview, $context, $widget_x, $widget_y, $data, $info, $time) = @_;
    my @uris = Gnome2::VFS::URI->list_parse($data->data);
    for my $uri (@uris) {
      print "received %s\n", $uri->to_string();
    }
  }

-- Dave O

How do I scroll to the bottom of a TextView?

This is often asked in the context of "How do i keep the TextView scrolled to the bottom when i add new text at the bottom?" The solution is to set a mark in the TextBuffer, and scroll to that mark.

use Glib ':constants';
use Gtk2 '-init';

# create a window with a scrolled text view.
my $window = Gtk2::Window->new();
$window->signal_connect(destroy => sub { Gtk2->main_quit });
$window->set_default_size(450, 200);

my $scroll = Gtk2::ScrolledWindow->new();
$scroll->set_policy('never', 'automatic');

my $textview = Gtk2::TextView->new();
$scroll->add($textview);
$window->add($scroll);
$window->show_all();

my $buffer = $textview->get_buffer();

# create a mark at the end of the buffer, with right gravity,
# so that when you insert text, the mark always stays on
# the right (at the end).
my $end_mark = $buffer->create_mark ('end', $buffer->get_end_iter, FALSE);

# every time we insert text, scroll to that mark.
$buffer->signal_connect (insert_text => sub {
    $textview->scroll_to_mark ($end_mark, 0.0, TRUE, 0.0, 1.0);
});

# display the output of some long-running command...
open my $pipe, 'sleep 1; ls -l |'
    or die "Unable to open pipe: $!\n";

Glib::IO->add_watch (fileno $pipe, ['in', 'hup'], sub {
    my ($fd, $condition) = @_;

    if ($condition >= 'in') {
        while (<$pipe>) {
            $buffer->insert ($buffer->get_end_iter, $_);
        }
    }

    if ($condition >= 'hup') {
        close $pipe;
        return FALSE;
    }

    return TRUE;
});

Gtk2->main();

0;

How do I set the background/foreground color of a Gtk2::CellRenderer?

There Is More Than One Way To Do It (obviously).

You can create a cell data function, and attach it to the column where you want to put your cell renderer in:

use constant COLUMN_TEXT => 0;
my $model = Gtk2::ListStore->new('Glib::String');

$model->set($model->append, COLUMN_TEXT, 'foo' );
$model->set($model->append, COLUMN_TEXT, 'bar' );
$model->set($model->append, COLUMN_TEXT, 'baz' );
$model->set($model->append, COLUMN_TEXT, 'blah');

my $view = Gtk2::TreeView->new($model);
my $cell = Gtk2::CellRendererText->new;
my $column = Gtk2::TreeViewColumn->new_with_attributes('My Column',
                                                       $cell,
                                                       text => COLUMN_TEXT);
$column->set_cell_data_func($cell, sub {
        my ($column, $cell, $model, $iter) = @_;
        if    ($model->get($iter, COLUMN_TEXT) eq 'foo') {
            # this offers a bit more flexibility
            $cell->set('background-gdk', Gtk2::Gdk::Color->parse('#ff0000'));
        }
        elsif ($model->get($iter, COLUMN_TEXT) eq 'bar') {
            # this is more straightforward
            $cell->set('background', 'blue'));
        }
        else                                             {
            # this is important, since we are using the same cell renderer
            # for a column.
            $cell->set('background-set', FALSE);
        }
    });

$view->append_column($column);

Beware that cell data function gets called pretty often, so it could become a bottleneck quite fast.

You might want to store the color inside the model itself, in a column not attached to a Gtk2::TreeViewColumn, and attach the background property of the cell renderer when adding it to the column:

use constant {
    COLUMN_TEXT  => 0,
    COLUMN_COLOR => 1,
};
my $model = Gtk2::ListStore->new('Glib::String', 'Glib::String');
$model->set($model->append, COLUMN_TEXT, 'foo',  COLUMN_COLOR, 'red'  );
$model->set($model->append, COLUMN_TEXT, 'bar',  COLUMN_COLOR, 'blue' );
$model->set($model->append, COLUMN_TEXT, 'baz',  COLUMN_COLOR, undef  ); # undef means 'no color'
$model->set($model->append, COLUMN_TEXT, 'blah', COLUMN_COLOR, 'green');

my $view = Gtk2::TreeView->new($model);

my $column = Gtk2::TreeViewColumn->new_with_attributes('My Column',
                                                       Gtk2::CellRendererText->new,
                                                       text => COLUMN_TEXT,
                                                       background => COLUMN_COLOR);
$view->append_column($column);

-- ebassi and others

Developing Your Own Widgets with Gtk2-Perl

How do I create a new widget as a subclass of an existing Gtk widget?

If you're only wanting to add a few convience functions or add some simple funcality, serialization would be a great example of something useful to do, all that may be required is 'use base'. Gtk2::SimpleMenu is an great example of such a widget. Trumped up trivial example:

  package Gtk2::EntryPlus;
  
  use strict;
  use warnings;
  use Carp;
  use Gtk2;
  use base 'Gtk2::Entry';

  
  sub new
  {
        my $class = shift;
        # create an entry
        my $self = Gtk2::Entry->new(@_);
        # rebless it to an Gtk2::EntryPlus
        bless $self, $class;
        return $self;
  }
  
  sub show
  {
          my $entryplus = shift;
          # this doesn't do anything but show you how to call 
          # a parent method if you really override this function
          # you'd do something here. note that this won't really
          # work as you'd expect for various reasons explained in
          # Glib::Subclass, take a look at that if you're wanting
          # to override C object functions. This is just an
          # example of using SUPER
          $entryplus->SUPER::show;
  }
  
  sub save_to_file
  {
          my $entryplus = shift;
          my $filename = shift;
          
          open my $out, '>', $filename
                  or croak "ERROR: unable to open file "
                          ."($filename) for output";
          print $out $entryplus->get_text;
          close $out;
  }
  
  sub load_from_file
  {
          my $entryplus = shift;
          my $filename = shift;
          
          open my $in, '<', $filename
                  or croak "ERROR: unable to open file "
                          ."($filename) for output";
          $entryplus->set_text(do { local $/; <$in> });
  }
  
  package MAIN;
  
  use Gtk2 '-init';
  
  my $win = Gtk2::Window->new;
  my $entryplus = Gtk2::EntryPlus->new;
  $entryplus->set_text('Hello');
  $entryplus->save_to_file('entryplus.txt');
  Glib::Timeout->add( 1000, sub {
                $entryplus->set_text('World');
                0;
        });
  Glib::Timeout->add( 2000, sub {
                $entryplus->load_from_file('entryplus.txt');
                # we should be back to 'Hello' here
                0;
        });
  $win->add($entryplus);
  $entryplus->show;
  $win->show;
  Gtk2->main;

For information on more advanced features that will let you do things like add signals and properties to your widget take a look at Glib::Object::Subclass, and this post in gtk-perl-list.

Wrapping C Gtk+ Modules/Widgets in Gtk2-Perl

I want to use the FooFrobnicator library with gtk2-perl, where are the perl bindings?

if FooFrobnicator is not a core library used by one of the maintainers, we probably haven't wrapped it. however, it's really easy to write your own wrappers. (hint, hint)

gtk2-perl is highly modular and extensible, so that we don't have to maintain an integrated package binding all available C libraries. This also makes it very easy for you to write your own bindings for GLib- and/or Gtk+-based libraries. For example, independent projects exist (or have been discussed at some point) to create bindings for GStreamer, the Gimp, ZVT, and Scintilla, all based on gtk2-perl.

The Binding How-To explains how you'd go about writing an extension module for other libraries. It's actually quite easy, although the setup can be rather involved.

Other Miscellaneous Questions

Where's the Glade option to generate perl code?

Glade doesn't natively convert glade files to source code, it uses helper programs to do that. A few converters are included with Glade, but one for Perl is not included. The Glade2-compatible version of Glade2Perl, Glade2Perl-Two, has not been updated since very early versions of gtk2-perl.

The Gtk2::GladeXML module allows you to create your UI directly from the glade file (or buffer in memory) at runtime; this may prove a more fruitful route.

why aren't there any capitals letters, and why aren't the grammar correct in the documentation?

it cause I don't no know english and apparenly you're looking at a document that i wrote - rwmcfa1

What version supports the FooBar widget? Can i use Gtk2-Perl x.yy with gtk+ a.b.c?

gtk2-perl works with all versions of gtk+ 2.x. Newer versions of the bindings add support for the widgets and features of newer versions of gtk+. In all cases, the bindings must be built against the most recent version of gtk+ you want to support.

Gtk2

Supports

version

gtk+ 2.0

gtk+ 2.2

gtk+ 2.4

gtk+ 2.6

1.00x

yes

yes

no

no

1.02x

yes

yes

yes

no

1.04x

yes

yes

yes

no

1.06x

yes

yes

yes

no

1.08x

yes

yes

yes

yes

You can build Gtk2 1.04x against gtk+ 2.6.0, but it will not support for any of the new widgets in gtk+ 2.6 because 1.04x of the bindings simply doesn't know they exist and don't have GType to perl package name mappings or method wrappers for them.

You can build Gtk2 1.06x against gtk+ 2.0.6, and the support for widgets from later versions of gtk+ will be omitted at compile time. Because of this, if/when you upgrade gtk+ to 2.2 or 2.4, the bindings still won't know about the new widgets; the solution is simply to recompile (or reinstall) the bindings.

The reason for this is that we can have only the newest version on CPAN, but we don't want you not to be able to use the newest version just because your system is old. This scheme allows us to reply to all bug reports on old versions with "please use the latest stable version." :-)

For maximum portability and compatibility in your programs (remember that Red Hat 8.0 systems still exist and have only gtk+ 2.0.6. and Debian stable is really old...), you can use version information to decide at runtime whether to use new features. For example, you may want to use Gtk2::FileChooser if it's available, but fall back to Gtk2::FileSelection if not. See the Glib::version and Gtk2::version manpages for details on the version information APIs.

How do I know which version of Gtk2 and which version of Glib I am running ?

If you are too confused about which versions of Gtk2 and Glib you have on your system, try the following script.

use strict;
use Glib;
use Gtk2;

print "\n";
printf "Glib %s \n", $Glib::VERSION;
printf "Gtk2 %s \n", $Gtk2::VERSION;
print "\n";

# The version info stuff appeared in 1.040.
print "Glib built for ".join(".", Glib->GET_VERSION_INFO).", running with "
    .join(".", &Glib::major_version, &Glib::minor_version, &Glib::micro_version)
    ."\n"
  if $Glib::VERSION >= 1.040;
print "Gtk2 built for ".join(".", Gtk2->GET_VERSION_INFO).", running with "
    .join(".", &Gtk2::major_version, &Gtk2::minor_version, &Gtk2::micro_version)
    ."\n"
  if $Gtk2::VERSION >= 1.040;
print "\n";

Projects/GTK-Perl/FrequentlyAskedQuestions (last edited 2015-01-16 10:34:54 by EmmanueleBassi)