这是我的代码: 如果我尝试使用循环在屏幕上放置多张牌,我只能获得最后一张牌 如果我不使用循环并且只尝试处理一张卡就可以处理,那么该卡将被处理。 我的一些代码来自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;
}
答案 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 +本身)。或者您可以使用GtkDrawingArea和cairo自行完成所有绘图。