Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Perl-Gtk2::How to set a window background image.

by turo (Friar)
on Feb 14, 2006 at 09:32 UTC ( #530061=perlquestion: print w/replies, xml ) Need Help??

turo has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks!,

I'm playing with Gtk2 (thanks zentara for your conseil), i've read the wonderful quick tutorial/how-to/guide Gtk2-Perl Study Guide (very recommended); but it doesn't (nor the Gtk documentation) covers some gtk2-perl objects. :'(

My problem is the following: I want to create a window with a background taken from a pixmap (i read an image with Gtk2::Gdk::PixBuf and obtain a Gtk2::Gdk::Pixmap).

Researching a little bit, i found Gtk2 very close to X11 programming, there are windows and they can be 'drawable' windows, so we can paint over them any background color or he content of a pixmap.

There are two types of windows in Gtk2, Gtk2::Window which has the simplest interface, and allows you to do almost anything (heritage from Gtk2::Widget). And the Gtk2::Gdk::Window, a low level interface, which allows you to the same as in X11 programming (i feel the power ...). For this object, the manuals are a little bit obscure; and i cannot go further without asking for the monks wisdom: did you ever set a background using Gkt2? is there any other way to do it whithout figthing with the greatest docummentation of Gtk2::Gdk::Window? does exists any tutorial to explain how to create and use Gtk2::Gdk::Window? ...

I'm obfuscated, i will try to read the code (if i find it), and if i succeed i will tell to you, my fellowship brothers ...

Cheers

turo

perl -Te 'print map { chr((ord)-((10,20,2,7)[$i++])) } split //,"turo"'

Replies are listed 'Best First'.
Re: Perl-Gtk2::How to set a window background image.
by zentara (Archbishop) on Feb 14, 2006 at 12:52 UTC
    Yeah, I feel your pain with trying to get to the lowlevel stuff in the docs. For what it's worth, I asked a similar question awhile back on the gtk-perl maillist, on whether you could set a style from a base64 encoded xpm contained within the file. The answer was "no". You would need to write it to a temp file, then incorporate it in as a style.

    If you think about it, a background pixmap probably needs to be setup before anything can be drawn onto it. The normal method they are setting up, is to use styles, and have your pixmaps stored under a style name in the styles directory. So maybe it will take them a few years to get around to it. :-)

    Another problem I've experienced with a Gdk window, is that it is not there until the window is mapped onto the screen. In the code below, if you try to get the gdkwindow in the main program, before show_all() is called, it will be undefined. The following is the closet I could get to what you want to do. It runs without error, but the background does not change, neither for a pixmap, nor a color. There probably is some command needed to redraw the window? I don't know, but if you find a way, please post it.

    #!/usr/bin/perl use warnings; use strict; use Glib qw/TRUE FALSE/; use Gtk2 '-init'; my $rc_style = Gtk2::RcStyle->new; $rc_style->bg_pixmap_name('normal', 'bunny.xpm'); my $window = Gtk2::Window->new('toplevel'); $window->set_title('Embed test'); $window ->signal_connect( 'destroy' => \&delete_event ); $window->set_border_width(10); $window->set_size_request(500,500); $window->modify_style ($rc_style); my $vbox = Gtk2::VBox->new( FALSE, 6 ); $window->add($vbox); $vbox->set_border_width(2); my $hbox= Gtk2::HBox->new( FALSE, 6 ); $vbox->pack_end($hbox,FALSE,FALSE,0); $hbox->set_border_width(2); $vbox->pack_end (Gtk2::HSeparator->new, FALSE, FALSE, 0); my $button = Gtk2::Button->new_from_stock('gtk-quit'); $hbox->pack_end( $button, FALSE, FALSE, 0 ); $button->signal_connect( clicked => \&delete_event ); my $button1 = Gtk2::Button->new('Set BG'); $hbox->pack_end( $button1, FALSE, FALSE, 0 ); $button1->signal_connect( clicked => \&set_bg ); my $vbox1 = Gtk2::VBox->new( 0, 5 ); $vbox->pack_end ($vbox1, TRUE, TRUE, 0); my $btn = Gtk2::Button->new_from_stock('gtk-quit'); $btn->signal_connect( 'clicked' => \&delete_event ); $window->show_all(); Gtk2->main; ##################################### sub delete_event { Gtk2->main_quit; return FALSE; } ########################################## sub set_bg{ my @z_xpm = ( '20 3 2 1', ' c None', '+ c #1A1A1A', '+ + + + + + + + + + ', '+ + + + + + + + + + ', '+ + + + + + + + + + ',); my $gdkwindow = $vbox->window; print "$gdkwindow\n"; #my $colormap = Gtk2::Gdk::Colormap->get_system; my $colormap = $window->get_default_colormap; my $pixmap = Gtk2::Gdk::Pixmap->colormap_create_from_xpm_d (undef, $colormap, undef, @z_xpm ); # my $black = Gtk2::Gdk::Color->new (0,0,0); # $gdkwindow->set_background($black); $gdkwindow->set_back_pixmap($pixmap); $window->show_all(); }

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

      I was very upset and discouraged ... and when i was resigned to open and xpm image, load it to a pixmap, and then load it with the Gtk2::RcStyle as a background image ...
      when i received your reply ...
      The use of an XPM hardcoded into an array was like a deją vu ... I took my last breath and said i'm going to make the last effort ... and an hour after ... tachan!!!!!

      I can load any image (jpeg, png ... and all those supported by the gdkPixbuf) to a background. Here is the code, modified from the one you submitted (i've only change the set_bg function ...)

      #!/usr/bin/perl use warnings; use strict; use Glib qw/TRUE FALSE/; use Gtk2 '-init'; my $rc_style = Gtk2::RcStyle->new; $rc_style->bg_pixmap_name('normal', 'bunny.xpm'); my $window = Gtk2::Window->new('toplevel'); $window->set_title('Embed test'); $window ->signal_connect( 'destroy' => \&delete_event ); $window->set_border_width(10); $window->set_size_request(500,500); $window->modify_style ($rc_style); my $vbox = Gtk2::VBox->new( FALSE, 6 ); $window->add($vbox); $vbox->set_border_width(2); my $hbox= Gtk2::HBox->new( FALSE, 6 ); $vbox->pack_end($hbox,FALSE,FALSE,0); $hbox->set_border_width(2); $vbox->pack_end (Gtk2::HSeparator->new, FALSE, FALSE, 0); my $button = Gtk2::Button->new_from_stock('gtk-quit'); $hbox->pack_end( $button, FALSE, FALSE, 0 ); $button->signal_connect( clicked => \&delete_event ); my $button1 = Gtk2::Button->new('Set BG'); $hbox->pack_end( $button1, FALSE, FALSE, 0 ); $button1->signal_connect( clicked => \&set_bg ); my $vbox1 = Gtk2::VBox->new( 0, 5 ); $vbox->pack_end ($vbox1, TRUE, TRUE, 0); my $btn = Gtk2::Button->new_from_stock('gtk-quit'); $btn->signal_connect( 'clicked' => \&delete_event ); $window->show_all(); Gtk2->main; ##################################### sub delete_event { Gtk2->main_quit; return FALSE; } #### sub set_bg{ #### PNG & Pixbuff :-) my $values; my ($widget, $context, @other_params) = @_; my $colormap = $window->get_default_colormap; my $pixbuff = Gtk2::Gdk::Pixbuf->new_from_file("figure.png"); my $graphicContext = Gtk2::GC->get(Gtk2::Gdk::Visual->get_best_depth, $colormap, $values); $pixbuff->render_to_drawable($widget->get_parent_window, $graphicContext, 0,0,0,0,500,500,'normal',0,0); }

      The conclusion, is:
      In X11 programming, you can draw anything to any 'drawable' window (i'm not an expert, but this is correct), With the help of Gtk2::Widget::get_parent_window we obtain a Gtk2::Gdk::Window which is a Gtk2::Gdk::Drawable. Once we got a drawable window, i think we can do almost anything with it (low level :') ... and low docummented)

      Okay, alls seems to be fine, but i have other problem now; how i obtain a Gtk2::Gdk::Window without waiting to the execution of the callback function? ... We need a kind of casting function!!!! ... Ideas?


      Cheers
      turo



      (... thanks zentara!!! ...)

      perl -Te 'print map { chr((ord)-((10,20,2,7)[$i++])) } split //,"turo"'
        Hi, I think you are on the right track. I was experimenting with a Drawable area. I tried your code, but I am getting segmentation faults. :-( I'm using Gtk+2.8.11. Anyways, I will experiment with your code, and hope I can get it to go.

        Alot of the problem, is the non-intuitive nature of the Gtk2 objects, somethings can be written on, and somethings are only containers. It might be smart of you to ask muppet on the gtk-perl maillist. If anyone knows, it would be him.


        I'm not really a human, but I play one on earth. flash japh
Re: Perl-Gtk2::How to set a window background image.
by zentara (Archbishop) on Feb 14, 2006 at 23:45 UTC
    Hi, I got it to work, yeah!! I narrowed down my segfault to some weird problem where you get the $graphicContext. Your method didn't work for me, and below is what I had to do. I'll post a better example, after I look at it awhile. It is important to match the size of the image to the window, etc. But here is the sub that works for me.
    sub set_bg{ my $pixbuff = Gtk2::Gdk::Pixbuf->new_from_file("1Zen16.png"); #set the new pixbuff in a vbox my $gdkwindow = $vbox1->window; # how to get the drawable, $widget->get_parent_window # did not work for me # although the drawable seems to have # the identical hash # ???? my ($drawable, $x_offset, $y_offset) = $gdkwindow->get_internal_paint_info; print "$drawable, $x_offset, $y_offset\n"; my $gc = Gtk2::Gdk::GC->new ($gdkwindow, undef); print "$gc\n"; $pixbuff->render_to_drawable($drawable, $gc, 0,0,0,0,500,430,'normal',0,0); #this was needed, to make the image actually change Gtk2->main_iteration while Gtk2->events_pending; $window->show_all(); return FALSE; }

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

      zentara i need time to digest this ... I suposse, i must read a gtk2 tutorial in C, and then read seriusly the Gtk2-perl docs (maybe this weekend)...

      For what i wanted to do, i finally use xpm images, preload them onto a pixmap, and then use the Gtk2::RcStyle for change my style everytime i want to...
      But, this invitation to master the Gtk2, calls me like the Dark Power ... (Gtk2 for perl is the simplest (forgetting our problems) API for programming user graphics interfaces ... but now ... now Gtk2 will be as powerfull for us like programming over X11 with the Xlibs ... )

      Forgetting my delirium; I've changed your "set_bg" version. It works fine, but i've simplified it:

      sub set_bg{ my $pixbuff = Gtk2::Gdk::Pixbuf->new_from_file("1Zen16.png"); #set the new pixbuff in a vbox my $gdkwindow = $vbox1->window; my $gc = Gtk2::Gdk::GC->new ($gdkwindow, undef); $pixbuff->render_to_drawable($gdkwindow, $gc, 0,0,0,0,500,430,'normal',0,0); return FALSE; }
      When you paint over a drawable, you only need to Sync the window, but this is a job for the Gtk2::main, no?

      I'm anxious for the weekend to come!

      turo

      perl -Te 'print map { chr((ord)-((10,20,2,7)[$i++])) } split //,"turo"'
        i need time to digest this

        I agree. There are some complications which set in, when you reset the background of a window that is already mapped to the screen. I noticed that if the dimensions of the render_to_drawable is not exactly the same as pixbuf dimensions, x-y errors would occur. These can be avoided by some logic to get the pixbuf x and y size, etc. But that brings up the problem of what happens if you resize the window? Will the image resize? How would you tile the image? etc.

        I was thinking about it last night, and the gtk c-libs developers probably didn't want to bloat the code with all the logic it would take to enable swappable background images. So we see it can be done, but the provided methods of using the styles and xpm files, is easier, and will probably work well for most applications.


        I'm not really a human, but I play one on earth. flash japh
Re: Perl-Gtk2::How to set a window background image.
by turo (Friar) on Feb 14, 2006 at 10:34 UTC

    Ok, yesterday I found some clues, but i must use a xpm file (Re: Background image for a window) ...

    my $rc_style = Gtk2::RcStyle->new; $rc_style->bg_pixmap_name ('normal', 'keyboard.xpm'); $window->modify_style ($rc_style);
    i will abandon the attempt to explore the GTk2::Gdk::Window ... :'( ...

    turo

    perl -Te 'print map { chr((ord)-((10,20,2,7)[$i++])) } split //,"turo"'
Re: Perl-Gtk2::How to set a window background image.
by renegadex (Beadle) on Nov 22, 2008 at 03:07 UTC
    try this.. i got it from the php cookbook. and converted it to perl.
    my $back_pixbuf = Gtk2::Gdk::Pixbuf->new_from_file($image); my ($pixmap,$mask) = $back_pixbuf->render_pixmap_and_mask(255); my $style = $window->get_style(); $style=$style->copy(); $style->bg_pixmap("normal",$pixmap); $window->set_style($style);
      Very cool renegadex, and ++ for the clever way you posted it twice......you deserve bonus points for figuring that one out. :-)

      I'm not really a human, but I play one on earth Remember How Lucky You Are
        Hehe, tnx zentara! I'm glad that I was able to contribute something. :D Tnx for all the help too! :D
Re: Perl-Gtk2::How to set a window background image.
by VVelox (Initiate) on May 29, 2009 at 22:49 UTC
    Any one have any suggestion on how to get this to work with the root window?

    The code below works, but it does not change it permanently. As soon as I move a window or etc, that part of the root window that was revealed goes back to the previous back ground.

    sub setBGfile{
    my $self=$_[0];
    my $file=$_1;

    Gtk2->init;

    my $screen=Gtk2::Gdk::Screen->get_default;
    my $window=$screen->get_root_window;

    my $pixbuf=Gtk2::Gdk::Pixbuf->new_from_file($file);

    my $values;
    my $colormap = $screen->get_default_colormap;

    my ($real_drawable, $x_offset, $y_offset) = $window->get_internal_paint_info;
    my $gc = Gtk2::Gdk::GC->new ($window, undef);

    $pixbuf->render_to_drawable($real_drawable, $gc,
    0,0,0,0,871,1200,'normal',0,0);

    Gtk2->main_iteration while Gtk2->events_pending;

    return;
    }

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://530061]
Approved by marto
Front-paged by Courage
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (3)
As of 2023-03-30 18:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Which type of climate do you prefer to live in?






    Results (74 votes). Check out past polls.

    Notices?