2011-09-29 34 views
4

我一直試圖在gtk小部件上設置背景圖像而沒有成功,即使在嘗試了4種不同的方法之後。在gtk中繪製背景圖像 - 我的任何嘗試都沒有工作

以下程序包含3種方法(第4種方法不涉及代碼)。我使用MinGW(g ++ 4.5.0)和gtkmm 2.4編譯它。可以將APPROACH宏設置爲1,2或3以選擇要編譯的方法。我還在評論中添加了參考文獻,以便您瞭解我從哪裏獲取想法。

#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> 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; 
} 

鏈接圖片我用:header.jpgbackground.jpg

佈局模仿我的實際方案。主窗口包含一個Gtk :: VBox,頂部有一個標題圖像,底部有一個Gtk :: Alignment。這種對齊的內容會隨着時間而改變,但我希望它有一個始終可見的背景圖像。

當加載根本沒有背景,正確的頭部圖像加載和窗口看起來是這樣的:

enter image description here

方法1是一個更接近的工作,但它隱藏標籤和按鈕:

enter image description here

途徑2和看起來與加載無背景相同。此外,方法2給了我以下錯誤信息:

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

最後,在方法4,我試圖通過添加以下行

bg_pixmap[NORMAL] = "D:\\path\\to\\file\\background.jpg" 
修改共享\主題\ MS-WINDOWS \ GTK-2.0

樣式爲「msw-default」部分。它也不起作用。

那麼,有沒有人成功地在Gtk小部件上繪製背景圖像?這可能嗎?我的代碼中的任何更改會使其工作?任何解決方法?

非常感謝所有幫助。

回答

7

我想我已經自己解決了。使用方法1,但改變這一行

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

此:

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

這樣,GTK調用自己的處理程序之前調用drawBackground發生。

enter image description here

我還要指出的是,在一個真正的程序,圖像將被一次的drawBackground外部加載。