Frage

The Pixbuf method doesn't work anymore for GTK3+ because obsoleted/removed. I want to put a background image in the back of a GtkFixed, on the gdk part of the GtkWindow or a GtkBox. I believe I need Cairo graphics library to do this.

Can a pleasant soul guide me in the right direction?

War es hilfreich?

Lösung

I have hacked an example together. It fills the background of the toplevel application window with an image.

As background image i choosed a little star (1). To compile the example invoke gcc like

gcc `pkg-config --libs --cflags glib-2.0 gtk+-3.0` <source> -o <executable>

On my machine the result looks like

view of the toplevel application window

1 : http://upload.wikimedia.org/wikipedia/commons/thumb/b/b2/Featured_Star_green.svg/32px-Featured_Star_green.svg.png


#include <gtk/gtk.h>
#include <glib-2.0/glib.h>

typedef struct Texture_
{
    gint root_width, root_height;
    cairo_surface_t *bg_image;
} Texture;

typedef struct Ui_
{
    GtkWidget *window;
    GtkWidget *grid;
    GtkWidget *button;

    Texture *texture;

    gulong window_draw_cb_handler_id;
} Ui;

gboolean window_draw_cb (GtkWidget *, cairo_t *, Ui *);

void
button_clicked_cb (GtkWidget * widget, Ui * ui)
{
    gboolean ret;

    ret =
        g_signal_handler_is_connected (ui->window,
                                       ui->window_draw_cb_handler_id);

    if (ret) {
        g_signal_handler_disconnect (ui->window, ui->window_draw_cb_handler_id);
    }
    else {
        ui->window_draw_cb_handler_id =
            g_signal_connect (ui->window, "draw", G_CALLBACK (window_draw_cb),
                              ui);
    }

    gtk_widget_queue_draw (ui->window);
}

void
destroy_cb (GtkWidget * widget, gpointer data)
{
    gtk_main_quit ();
}

gboolean
window_draw_cb (GtkWidget * widget, cairo_t * cr, Ui * ui)
{

    cairo_set_source_surface (cr, ui->texture->bg_image, 0, 0);

    cairo_rectangle (cr, 0, 0,
                     ui->texture->root_width, ui->texture->root_height);

    cairo_fill (cr);

    /* draw all widgets attached to `grid` to the
     * cairo context of the mainwindow */

    gtk_widget_draw (ui->grid, cr);
    cairo_fill (cr);

    return TRUE;
}

void
ui_texture_init (Ui * ui)
{
    gint root_width, root_height, width, height;
    guint n_x, n_y, i, k;
    cairo_format_t format;
    cairo_surface_t *bg_image, *target;
    cairo_status_t ret;
    GdkWindow *root;
    cairo_t *cr;

    ui->texture = g_new (Texture, 1);

    bg_image =
        cairo_image_surface_create_from_png ("./Featured_Star_green.svg.png");

    ret = cairo_surface_status (bg_image);

    g_assert (ret == 0);

    format = cairo_image_surface_get_format (bg_image);

    width = cairo_image_surface_get_width (bg_image);
    height = cairo_image_surface_get_height (bg_image);

    root = gdk_get_default_root_window ();

    gdk_window_get_geometry (root, NULL, NULL, &root_width, &root_height);

    target = cairo_image_surface_create (format, root_width, root_height);

    cr = cairo_create (target);

    n_x = root_width / width;
    n_y = root_height / height;

    for (i = 0; i <= n_x; i++) {

        for (k = 0; k <= n_y; k++) {
            cairo_set_source_surface (cr, bg_image, i * width, k * height);

            cairo_rectangle (cr, i * width, k * height, width, height);

            cairo_fill (cr);
        }
    }

    ui->texture->root_width = root_width;
    ui->texture->root_height = root_height;

    ui->texture->bg_image = target;
}

void
forall_container (GtkWidget * widget, gpointer data)
{

    gtk_widget_set_halign (widget, GTK_ALIGN_CENTER);
    gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
    gtk_widget_set_margin_top (widget, 10);
    gtk_widget_set_margin_bottom (widget, 10);
    gtk_widget_set_margin_left (widget, 10);
    gtk_widget_set_margin_right (widget, 10);
}

Ui *
ui_init ()
{
    Ui *ui;

    GtkWidget *label, *entry;
    PangoAttrList *attributes;

    ui = g_new (Ui, 1);

    ui_texture_init (ui);

    ui->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

    ui->grid = gtk_grid_new ();

    gtk_grid_set_column_homogeneous (GTK_GRID (ui->grid), TRUE);
    gtk_grid_set_row_homogeneous (GTK_GRID (ui->grid), TRUE);
    gtk_grid_set_row_spacing (GTK_GRID (ui->grid), 10);

    label = gtk_label_new ("Label:");

    attributes = pango_attr_list_new ();

    pango_attr_list_insert (attributes, pango_attr_size_new_absolute (30000));

    gtk_label_set_attributes (GTK_LABEL (label), attributes);
    entry = gtk_entry_new ();
    ui->button = gtk_button_new_with_label ("Toggle background image");

    gtk_grid_attach (GTK_GRID (ui->grid), label, 0, 0, 1, 1);
    gtk_grid_attach (GTK_GRID (ui->grid), entry, 1, 0, 1, 1);
    gtk_grid_attach (GTK_GRID (ui->grid), ui->button, 0, 1, 2, 1);

    gtk_container_foreach (GTK_CONTAINER (ui->grid), &forall_container, NULL);

    gtk_container_add (GTK_CONTAINER (ui->window), ui->grid);

    return ui;
}

int
main (int argc, char *argv[])
{

    Ui *ui;

    gtk_init (&argc, &argv);

    ui = ui_init ();

    g_signal_connect (ui->window, "destroy", G_CALLBACK (destroy_cb), ui);

    ui->window_draw_cb_handler_id =
        g_signal_connect (ui->window, "draw", G_CALLBACK (window_draw_cb), ui);

    g_signal_connect (ui->button, "clicked", G_CALLBACK (button_clicked_cb),
                      ui);

    gtk_widget_show_all (ui->window);

    gtk_main ();
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top