如何在GTK的图形屏幕上处理多个图像?

时间:2013-10-09 04:10:10

标签: gtk

这是我的代码: 如果我尝试使用循环在屏幕上放置多张牌,我只能获得最后一张牌 如果我不使用循环并且只尝试处理一张卡就可以处理,那么该卡将被处理。 我的一些代码来自Stack Overflow,有些来自其他来源。我已经得到了“设置甲板”,“洗牌”,大部分时间都在完成手工操作,但这让我很难过。

#include <cairo.h>
#include <gtk/gtk.h>

/*  Global Structure to hold
1. The image to be moved across the screen
2. The main window
3. The fixed surface so that I can place event boxes on it
4. The Start and End locations for the image
5. a counter
6. an animation counter
7. a boolean timer
8. a tid for the timeout
*/
struct {
    GtkWidget   *image;
    GtkWidget   *window;
    GtkWidget   *fixed;
    gint        initC, initR;
    gint        endC, endR;
    gint        count;
    gint        animations;
    gboolean    timer;
    guint       tid;
} glob;

// finalizes g_object_weak_ref for images

static void finalized(G_GNUC_UNUSED gpointer unused, G_GNUC_UNUSED GObject *Data)
{
g_print("Card finalized.\n");
}

// my drawing routine from Stack OverFlow

static void do_drawing()
{
  gint x, y;
  gdouble scale;

        // The scale tells us where to place the image

        scale = (gdouble) glob.count / (gdouble) glob.animations;

        // The new position adds the progress to the initial
        x = (scale * (glob.endC - glob.initC)) + glob.initC;
        y = (scale * (glob.endR - glob.initR)) + glob.initR;
        g_object_ref(glob.image);
        g_object_weak_ref(G_OBJECT(glob.image), finalized, NULL);
        if(glob.count == 0 )
           { gtk_fixed_put ((GtkFixed *)glob.fixed, glob.image, x, y); }
        gtk_fixed_move ((GtkFixed *)glob.fixed, glob.image , x, y);
        gtk_widget_show(glob.image);
        glob.count++;
        // If this has run 'animations' times, remove
        // the timeout by returning FALSE
    if(glob.count >= glob.animations)
    glob.timer = FALSE;

  // Otherwise, continue running the timeout

}
// time handler for g_timeout_add

static gboolean time_handler()
{
  if (glob.timer == FALSE) return FALSE;
    do_drawing();
  return TRUE;
}

static void deal()
{
//  Initialize the cards to deal
    gchar   *names[7] = { "Card1.png", "Card2.png", "Card3.png", "Card4.png", "Card5.png", "Card6.png", "Card7.png" };
    guint   i = 0;

//  Initialize the global holder for the animation
//  with the start location and end location
//  initC = initial Column, initR = initial Row
    glob.timer = TRUE;
    glob.count = 0;
    glob.initC = 500;
    glob.initR = 15;
    glob.endC = 5;
    glob.endR = 495;
    glob.animations = 50;

    /*  This does not work it only shows
    the last iteration of the images (Card7)
    if I do not use a loop and only do
    one, it works just fine but only for one card
*/
       do
        {
            glob.image = gtk_image_new_from_file(names[ i ]);
            glob.tid = g_timeout_add( 530, (GSourceFunc) time_handler, NULL);
            g_print("Tid = %d \n", glob.tid);
            glob.endC = glob.endC + 70;
            i++;
/*  If I try to use g_source_remove nothing works
//            g_source_remove(glob.tid);
*/
        } while( i < 7 );

}

int main(int argc, char *argv[])
{
    GtkWidget *bkgd;
     gint    i;

    gtk_init(&argc, &argv);

    glob.fixed = gtk_fixed_new();
    bkgd  = gtk_image_new_from_file ( "BackGround.jpg");
    gtk_container_add(GTK_CONTAINER(glob.fixed), bkgd);

    glob.window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_container_add(GTK_CONTAINER(glob.window), glob.fixed);
    g_signal_connect(glob.window, "destroy",
        G_CALLBACK (gtk_main_quit), NULL);

    gtk_window_set_position(GTK_WINDOW(glob.window), GTK_WIN_POS_CENTER);
    gtk_window_set_default_size(GTK_WINDOW(glob.window), 1000, 550);
    gtk_window_set_title(GTK_WINDOW(glob.window), "Image");

        deal();

    gtk_widget_show_all(glob.window);

    gtk_main();

//    Apparently not needed
//    g_object_unref(glob.image);

  return 0;
}

2 个答案:

答案 0 :(得分:0)

在你的循环中,你有

glob.image = gtk_image_new_from_file(names[i]);
glob.tid = g_timeout_add( 530, (GSourceFunc) time_handler, NULL);

530ms后,您的time_handler()功能运行七次。但是,到目前为止,全局glob.image已设置为卡片7的图像,因此您的绘图功能每次都会绘制卡片图像。

相反,您需要将刚刚加载的图像传递给超时功能。有点像:

GtkWidget *image = gtk_image_new_from_file(names[i]);
g_object_ref_sink(image);
g_timeout_add(530, (GSourceFunc) time_handler, image);

应该有效。您还需要将time_hander()功能更改为:

static gboolean time_handler(gpointer data)
{
    GtkImage *image = GTK_IMAGE(data);
    if (glob.timer == FALSE) return FALSE;
        do_drawing(image);
    g_object_unref(image);
    return TRUE;
}

并修改您的do_drawing()函数以绘制传递的GtkImage*而非全局glob.image

答案 1 :(得分:0)

GtkFixed用于将小部件放置在固定位置,但您需要的更多可能是画布小部件。有several ones available并且社区尚未就最佳设计达成共识(理想情况下进入GTK +本身)。或者您可以使用GtkDrawingAreacairo自行完成所有绘图。