You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Gtk 3与Cairo实现随机位置图片旋转遇阻求助

Fixing Random Position & Rotation for Images in GTK

Hey there! I get that you're trying to make an image rotate at random positions using GTK but hitting snags with your code. Let's break down what's likely missing and get this working properly.

First, let's fill in the gaps in your original code snippet—you probably didn't set up a timer to trigger rotations, handle random position generation correctly, or properly apply Cairo transformations. Here's a complete, working version of the code with clear explanations:

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

GtkWidget *window;
GtkWidget *img;
gdouble rotation_angle = 0.0;
gint random_x = 0;
gint random_y = 0;

static void rotate_cb() {
    // Increment rotation angle (adjust the value to change rotation speed)
    rotation_angle += 5.0;
    if (rotation_angle >= 360.0) {
        rotation_angle = 0.0;
    }

    // Generate new random position that keeps the entire image inside the window
    gint win_w = gtk_widget_get_allocated_width(window);
    gint win_h = gtk_widget_get_allocated_height(window);
    gint img_w = gtk_widget_get_allocated_width(img);
    gint img_h = gtk_widget_get_allocated_height(img);
    random_x = rand() % (win_w - img_w);
    random_y = rand() % (win_h - img_h);

    // Tell GTK to redraw the window with updated values
    gtk_widget_queue_draw(window);
}

static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr, gpointer data) {
    if (!img) return FALSE;

    gint img_w = gtk_widget_get_allocated_width(img);
    gint img_h = gtk_widget_get_allocated_height(img);

    // Save the current Cairo state to avoid messing up other draws
    cairo_save(cr);

    // Move the drawing origin to the center of our random position
    cairo_translate(cr, random_x + img_w/2, random_y + img_h/2);
    // Rotate the context (convert degrees to radians since Cairo uses radians)
    cairo_rotate(cr, rotation_angle * G_PI / 180.0);
    // Shift back so the image rotates around its own center, not the origin
    cairo_translate(cr, -img_w/2, -img_h/2);

    // Draw the image using GTK's icon renderer
    gtk_render_icon(GTK_WIDGET(widget), GTK_IMAGE(img)->storage, gtk_widget_get_state_flags(widget),
                    img_w, img_h, NULL, cr);

    // Restore the original Cairo context state
    cairo_restore(cr);

    return TRUE;
}

int main(int argc, char *argv[]) {
    gtk_init(&argc, &argv);
    srand(time(NULL)); // Seed the random number generator

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_default_size(GTK_WINDOW(window), 600, 400);
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);

    // Load your image (replace "your_image.png" with your actual image path)
    img = gtk_image_new_from_file("your_image.png");
    if (!img) {
        g_print("Failed to load image!\n");
        return 1;
    }

    // Use a drawing area to handle custom Cairo rendering
    GtkWidget *drawing_area = gtk_drawing_area_new();
    gtk_container_add(GTK_CONTAINER(window), drawing_area);
    g_signal_connect(drawing_area, "draw", G_CALLBACK(on_draw_event), img);

    // Set up a timer to update rotation/position every 50ms (adjust for speed)
    g_timeout_add(50, (GSourceFunc)rotate_cb, NULL);

    gtk_widget_show_all(window);
    gtk_main();

    return 0;
}

Key Fixes & Explanations:

  • Random Position Logic: We calculate positions that ensure the whole image stays inside the window by subtracting the image's dimensions from the window's size before generating random values.
  • Smooth Rotation: Cairo uses radians, so we convert our degree-based angle. The double translation trick makes the image rotate around its own center instead of the window's top-left corner.
  • Timer Trigger: g_timeout_add calls our update function every 50ms to refresh the angle and position, then triggers a redraw to show the changes.
  • Custom Rendering: Using a GtkDrawingArea gives us full control over how the image is drawn, instead of relying on the default image widget behavior.

Compilation Note:

To compile this code (make sure you have GTK3 installed), run:

gcc -o rotating_image rotating_image.c `pkg-config --cflags --libs gtk+-3.0`

Just replace "your_image.png" with the path to your actual image, and you should see it rotating at random positions smoothly!

内容的提问来源于stack exchange,提问作者Andrew Shao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:59:46