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

Is there a way to change the background color of a Gtk2::Button widget? I have tried using modify_bg but it always causes an error.
#just some simple code, not tested my $window = Gtk2::Window->new( 'toplevel'); my $button = Gtk2::Button->new( 'NEW'); $window->add( $button); Gtk2->main;

Replies are listed 'Best First'.
Re: Gtk2: changing Button Color
by zentara (Cardinal) on Aug 21, 2007 at 11:39 UTC
    It's very difficult to do. I've been bitching about the difficulty of setting Gtk2 widget colors for awhile, and I'm constantly slapped down by the gurus, saying " you are not supposed to interfere with (or override) the themes setup by the user.

    Basically, a gtk2 app will check the theme settings in ~.gtk2rc-2.0 and holds onto them for dear life. Some you can override, but you generally need to override the theme settings explicitly, before you can change them.

    The following script tries to demonstrate it. My rc parsing dosn't seem to work for Buttons(for me anyways), but will work on window widgets. Anyways, I try to override the existing theme, then make new settings,but the override dosn't work. As proof of this, rename your .gtkrc-2.0 to .gtkrc-2.0zzz and run the script, and you will see the button color change. So...... what you probably need to do, is setup a custom .gtkrc-2.0 for your app, and at the very start of your script, parse your custom rc settings. I would guess that you would have to setup a resource directory for your script, and put your custom .gtkrc-2.0 in there.

    Like I said, try this after renaming your .gtkrc-2.0 and see the difference. I've included a second sample below, to show how to override a background pixmap.


    I'm not really a human, but I play one on earth. Cogito ergo sum a bum
Re: Gtk2: changing Button Color
by Anonymous Monk on Aug 21, 2007 at 06:18 UTC
      The problem with the below code ( taken from the links above) is that you cant have the color and the label on the same button. That is what I want to do. Any ideas? Another option would be to 'gray-out' the button.
      #!/usr/bin/perl -w use strict; package Mup::ColorButton; use Gtk2; use Glib::Object::Subclass Gtk2::Button::, signals => { color_changed => {}, show => \&on_show, }, properties => [ Glib::ParamSpec->int ( 'red', 'Red', 'The Red component of the RGB color', 0, 0xffff, 0xffff, [qw/readable writable/] ), Glib::ParamSpec->int ( 'green', 'Green', 'The Green component of the RGB color', 0, 0xffff, 0xffff, [qw/readable writable/] ), Glib::ParamSpec->int ( 'blue', 'Blue', 'The Blue component of the RGB color', 0, 0xffff, 0xffff, [qw/readable writable/] ), ] ; sub INIT_INSTANCE { my $self = shift; $self->{red} = 0xffff; $self->{green} = 0xffff; $self->{blue} = 0xffff; my $frame = Gtk2::Frame->new; $frame->set_border_width (3); $frame->set_shadow_type ('etched-in'); $self->add ($frame); $frame->show; my $event_box = Gtk2::EventBox->new; $event_box->set_size_request (14, 14); $frame->add ($event_box); $event_box->show; $self->{colorbox} = $event_box; } sub on_show { my $self = shift; $self->set_color (red => $self->{red}, green => $self->{green}, blue => $self->{blue}); $self->signal_chain_from_overridden; } sub set_color { my $self = shift; my %params = @_; my $color = Gtk2::Gdk::Color->new ($params{red}, $params{green}, $params{blue}); $self->{colorbox}->get_colormap->alloc_color ($color, 0, 1); $self->{colorbox}->modify_bg ('normal', $color); $self->{colorbox}->modify_bg ('active', $color); $self->{colorbox}->modify_bg ('prelight', $color); $self->{red} = $params{red}; $self->{green} = $params{green}; $self->{blue} = $params{blue}; $self->signal_emit ('color-changed'); } package main; use Gtk2 -init; my $window = Gtk2::Window->new; $window->set_title ('Color buttons'); $window->set_border_width (6); $window->signal_connect (delete_event => sub { Gtk2->main_quit; 1 }); my $vbox = Gtk2::VBox->new; $window->add ($vbox); $vbox->show; my $foo = Mup::ColorButton->new (red => 0xaaaa, green => 0x0, blue => +0xffff); $vbox->pack_start ($foo, 1, 1, 0); $foo->show; $foo->signal_connect (clicked => sub { my $self = shift; my $dialog = Gtk2::ColorSelectionDialog->new ('pick a +color'); my $c = Gtk2::Gdk::Color->new ($self->{red}, $self->{green}, $self->{blue}); $self->{colorbox}->get_colormap->alloc_color ($c, 0, 1 +); $dialog->colorsel->set_current_color ($c); if ('ok' eq $dialog->run) { my $c = $dialog->colorsel->get_current_color; $self->set_color (red => $c->red, green => $c->green, blue => $c->blue); } $dialog->destroy; }); $foo->signal_connect (color_changed => sub { warn "the color changed - now " . join (", ", $_[0]->get (qw/red green blue/)) . ". i should do something!"; }); $window->show; Gtk2->main;
        Yes you can, all you nee
Re: Gtk2: changing Button Color
by zentara (Cardinal) on Aug 22, 2007 at 12:32 UTC
    Hi, I asked on the Gtk2/Perl maillist and was given the tip, to set the %ENV variable to point to a custom gtkrc file. This will override the colors set as default in ~.gtkrc-2.0. Of course it requires you wrap your script in a wrapper, and you setup a (possibly empty) theme for your script, and put it in a resource directory.
    #!/bin/sh #wrapper to make custom theme for a Gtk2 app export GTK2_RC_FILES='/usr/local/share/themes/Bumblebee/gtk-2.0/gtkrc' ./button-color3-env-works # run the script

    I'm not really a human, but I play one on earth. Cogito ergo sum a bum
      To update this, for anyone searching, you don't need a wrapper for a Perl script (although it would be useful for a c program).

      Anyways, you can use a BEGIN block, or set the ENV and require Gtk2 instead of use to load it.

      What this script does, is load an empty gtkrc file (in the cwd), and it overrides the theme in the /home/user/.gtkrc-2.0 file. Thus making button color changes possible.

      #!/usr/bin/perl use warnings; use strict; use Glib qw/TRUE FALSE/; # must be before Gtk2 init #BEGIN { $ENV{GTK2_RC_FILES} = 'gtkrc_myapp' } #use Gtk2 '-init'; # or set and require module below $ENV{GTK2_RC_FILES} = 'gtkrc_myapp'; #require Foo; #Foo->import; # if necessary require Gtk2; Gtk2->init; my $window = Gtk2::Window->new('toplevel'); $window->set_title('Z'); $window ->signal_connect( 'destroy' => \&delete_event ); $window->set_border_width(10); $window->set_size_request(300,200); my $greyh = Gtk2::Gdk::Color->new (0xCCCC,0xCCCC,0xCCCC); my $greyl = Gtk2::Gdk::Color->new (0x9999,0x9999,0x9999); my $redh = Gtk2::Gdk::Color->new (0xFFFF,0,0); my $redl = Gtk2::Gdk::Color->new (0xAAAA,0,0); my $greenh = Gtk2::Gdk::Color->new (0,0xFFFF,0xEEEE); my $greenl = Gtk2::Gdk::Color->new (0,0xFFFF,0xCCCC); my $greend = Gtk2::Gdk::Color->new (0,0xFFFF,0); my $blueh = Gtk2::Gdk::Color->new (0,0xFFFF,0xFFFF); my $bluel = Gtk2::Gdk::Color->new (0,0xCCCC,0xFFFF); $window->modify_bg ('normal', $greenl); 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); my $frame0 = Gtk2::Frame->new('Controls'); $vbox->pack_end( $frame0, FALSE, FALSE, 0 ); $frame0->set_border_width(3); $frame0->modify_bg ('normal', $redl); #used for coloring frame my $coleventb0 = Gtk2::EventBox->new(); $frame0->add($coleventb0); my $hbox0 = Gtk2::HBox->new( FALSE, 6 ); $coleventb0->add($hbox0); $hbox0->set_border_width(3); $coleventb0-> modify_bg('normal', $greyl); my $button = Gtk2::Button->new_from_stock('gtk-quit'); $hbox0->pack_end( $button, FALSE, FALSE, 0 ); $button->signal_connect( clicked => \&delete_event ); my $button1 = Gtk2::Button->new('Color-test'); $hbox0->pack_end( $button1, FALSE, FALSE, 0 ); $button1->signal_connect( clicked => sub{ print chr(07),"\n"; # \n or use $|++ }); $button1->modify_bg ('normal', $bluel); $button1->modify_bg ('prelight', $blueh); $button1->modify_bg ('active', $greend); $coleventb0-> modify_bg('normal', $greyl); $window->show_all(); Gtk2->main; ##################################### sub delete_event { Gtk2->main_quit; return FALSE; }

      I'm not really a human, but I play one on earth. Cogito ergo sum a bum