开发者

Draw background image in gtk - none of my attempts work

I've been trying to set a background image on a gtk widget without success, even after trying 4 different approaches.

The following program contains 3 approaches (the 4th approach involves no code). I compiled it using MinGW (g++ 4.5.0) and gtkmm 2.4. The APPROACH macro can be set to 1, 2 or 3 in order to choose which approach to compile. I've also added references in the comments, so you can find out where I got the ideas from.

#include <iostream>
#include <gtkmm/main.h>
#include <gtkmm/alignment.h>
#include <gtkmm/box.h>
#include <gtkmm/entry.h>
#include <gtkmm/eventbox.h>
#include <gtkmm/frame.h>
#include <gtkmm/image.h>
#include <gtkmm/label.h>
#include <gtkmm/table.h>
#include <gtkmm/window.h>

// Set this to 1, 2 or 3 to try different ways of drawing the background
// Set to 0 to load no background at all
#define APPROACH (0)

// Making this alignment global in order to modify it from drawBackground
Gtk::Alignment* alignment;

bool drawBackground(GdkEventExpose* event) {
    std::cout << "Draw background" << std::endl;

    // Load background image
    Glib::RefPtr<Gdk::Pixbuf> pixbuf = Gdk::Pixbuf::create_from_file("background.jpg");
    Glib::RefPtr<Gdk::Pixmap> pixmap;
    Glib::RefPtr<Gdk::Bitmap> mask;
    pixbuf->render_pixmap_and_mask(pixmap, mask,0);

    {
        // Test that pixbuf was created correctly
        Glib::RefPtr<Gdk::Pixbuf> back_to_pixbuf = Gdk::Pixbuf::create((Glib::RefPtr<Gdk::Drawable>)pixmap, 0, 0, pixbuf->get_width(), pixbuf->get_height());
        back_to_pixbuf->save("back_to_pixbuf.png", "png");
    }

#if APPROACH == 1
    // Approach 1: draw_pixbuf
    // Ref: http://islascruz.org/html/index.php/blog/show/Image-as-background-in-a-Gtk-Application..html
    Glib::RefPtr<Gtk::Style> style = alignment->get_style();
    alignment->get_window()->draw_pixbuf(style->get_bg_gc(Gtk::STATE_NORMAL), pixbuf, 0, 0, 0, 200, pixbuf->get_width(), pixbuf->get_height(), Gdk::RGB_DITHER_NONE, 0, 0);
#endif

#if APPROACH == 2
    // Approach 2: set_back_pixmap
    // Ref: http://www.gtkforums.com/viewtopic.php?t=446
    //      http://stackoverflow.com/questions/3150706/gtk-drawing-set-background-image
    alignment->get_window()->set_back_pixmap(pixmap);
#endif
}

int main (int argc, char *argv[])
{
    Gtk::Main kit(argc, argv);

    Gtk::Window w;
    Gtk::VBox mainBox;

    // Top image
    Gtk::Image topImage("header.jpg");
    mainBox.pack_start(topImage,false,false,0);

    // Middle alignment
    alignment = Gtk::manage(new Gtk::Alignment);
    mainBox.pack_start(*alignment,true,true,0);

    // Create widget
    Gtk::Alignment mywidget(0.5, 0.5, 0.1, 0.9);
    Gtk::Table table;
    Gtk::Label label1("Username"); table.attach(label1,0,1,0,1);
    Gtk::Label label2("Password"); table.attach(label2,0,1,1,2);
    Gtk::Entry entry1;             table.attach(entry1,1,2,0,1);
    Gtk::Entry entry2;             table.attach(entry2,1,2,1,2);
    Gtk::Button button("Login");   table.attach(button,1,2,2,3);
    mywidget.add(table);

    // Put widget in middle alignment
    alignment->add(mywidget);

    // Try to change the background
#if APPROACH == 1 || APPROACH == 2
    alignment->signal_expose_event().connect(sigc::ptr_fun(&drawBackground), true);
#endif

#if APPROACH == 3
    // Approach 3: modify the style using code
    // Ref: http://www.gtkforums.com/viewtopic.php?t=446
    // Load background image
    Glib::RefPtr<Gdk::Pixbuf> pixbuf = Gdk::Pixbuf::create_from_file("background.jpg");
    Glib::RefPtr<Gdk::Pixmap> pixmap;
    Glib::RefPtr<Gdk::Bitmap> mask;
    pixbuf->render_pixmap_and_mask(pixmap, mask,0);
    Glib::RefPtr<Gtk::Style开发者_JS百科> style = alignment->get_style()->copy();
    style->set_bg_pixmap(Gtk::STATE_NORMAL,pixmap);
    style->set_bg_pixmap(Gtk::STATE_ACTIVE,pixmap);
    style->set_bg_pixmap(Gtk::STATE_PRELIGHT,pixmap);
    style->set_bg_pixmap(Gtk::STATE_SELECTED,pixmap);
    style->set_bg_pixmap(Gtk::STATE_INSENSITIVE,pixmap);
    alignment->set_style(style);
#endif

    // Approach 4: modify share\themes\MS-Windows\gtk-2.0
    // adding the following line
    // bg_pixmap[NORMAL] = "D:\\path\\to\\file\\background.jpg"
    // in the style "msw-default" section
    // Ref: http://lists.ximian.com/pipermail/gtk-sharp-list/2005-August/006324.html

    // Show the window
    w.add(mainBox);
    w.show_all();
    kit.run(w);
    return 0;
}

Links to images I used: header.jpg background.jpg

The layout mimics that of my actual program. The main window contains a Gtk::VBox with a header image on top and an Gtk::Alignment at the bottom. The contents of this alignment will change over time but I want it to have a background image always visible.

When loading no background at all, the header image loads correctly and the window looks like this:

Draw background image in gtk - none of my attempts work

Approach 1 is the one that is closer to work, though it hides the labels and the buttons:

Draw background image in gtk - none of my attempts work

Approaches 2 and 3 look the same as loading no background. Besides, approach 2 gives me the following error message:

(test-img-fondo.exe:1752): Gdk-CRITICAL **: gdk_window_set_back_pixmap: assertion `pixmap == NULL || !parent_relative' failed

Finally, in approach 4, I attempt to modify share\themes\MS-Windows\gtk-2.0 by adding the following line

bg_pixmap[NORMAL] = "D:\\path\\to\\file\\background.jpg"

in the style "msw-default" section. It doesn't work either.

So, has anyone succesfully drawn a background image on a Gtk widget? Is this possible at all? Any changes in my code that would make this work? Any workarounds?

All help is greatly appreciated.


I think I've solved it myself. Use approach 1 but change this line

alignment->signal_expose_event().connect(sigc::ptr_fun(&drawBackground), true);

for this:

alignment->signal_expose_event().connect(sigc::ptr_fun(&drawBackground), false);

This way, the call to drawBackground occurs before gtk calls its own handlers.

Draw background image in gtk - none of my attempts work

I should also point out that, in a real program, the images should be loaded once outside of drawBackground.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜