我想自动将GTK_WINDOW移动到屏幕上。目前我有一个绘制/移动循环,但这非常不稳定。我对GTK编程(以及一般的gui编程)非常陌生。我错过了什么?
答案 0 :(得分:5)
你还没有说过你希望窗口遵循什么样的路径。如果路径是一些简单的时间函数 - 也就是说,如果您有办法计算窗口在任何给定时间的位置 - 您可以尝试以下代码中说明的方法。对于示例中非常简单的菜单,它在我的Linux系统上运行正常并产生相当平滑的运动。
该方法的关键在于,不是每个定时器事件移动窗口给定距离,而是找出当前时间并将窗口移动到它应该处于的位置。因此,运动速度的时间导数应该是恒定的,即使定时器事件不规则地发生,也可以避免参差不齐或波动。 (如g-timeout-add() description所述,很容易发生不规则。)
在此示例中,路径从窗口的左上角到左下和后退,重复。 timerEvent()中的常量'HalfTime'控制从一个角落到另一个角落所需的时间。 g_timeout_add()调用中的常量3将计时器间隔设置为0.003秒,或每秒约333次移动(MPS)。 (您可能想尝试更合理的费率,例如20,30,40等MPS;我使用数字3,因为我在使用之前没有查找g-timeout-add(),并假设延迟是数字的秒,大约33 MPS,而不是毫秒,大约333 MPS。)如果您的窗口内容非常复杂,MPS将更少实用。此外,我尝试了一些较慢的速度,并得到了更多的波动的印象。
/* $Id: app12.c $
Re: animating position of a top-level Gtk window
jiw July 2011 -- Offered without warranty under GPL v3
terms per http://www.gnu.org/licenses/gpl.html */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <gtk/gtk.h>
typedef struct DATA { GTimer *timer; GtkWidget *window; int w, h; }
DataStruct;
gboolean timerEvent(void *dataset) {
enum { HalfTime=8, CycTime=2*HalfTime };
gulong micros;
DataStruct *data =dataset;
double t = fabs(fmod (g_timer_elapsed (data->timer, µs), CycTime));
int x = (t*data->w)/HalfTime, y = (t*data->h)/HalfTime;
gtk_window_move (GTK_WINDOW(data->window),
t<HalfTime? x : 2*data->w-x, t<HalfTime? y : 2*data->h-y);
return TRUE; /* Keep timeout running */
}
int main(int argc, char **argv) {
GtkWidget *vbox, *b;
GdkScreen *gds;
DataStruct data;
data.timer = g_timer_new();
gtk_init (&argc, &argv);
data.window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW(data.window), 200, 150);
g_signal_connect (G_OBJECT(data.window), "destroy",
G_CALLBACK(gtk_main_quit), NULL);
vbox = gtk_vbox_new (FALSE, 0);
gtk_container_add (GTK_CONTAINER(data.window), vbox);
b = gtk_button_new_with_label ("Click to Exit");
gtk_box_pack_start (GTK_BOX(vbox), b, TRUE, TRUE, TRUE);
g_signal_connect (b, "clicked", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all (data.window);
gds = gdk_screen_get_default (); /* Get pointer to screen */
data.w = gdk_screen_get_width (gds); /* Find out screen width */
data.h = gdk_screen_get_height (gds); /* Find out screen height */
printf ("Screen size = %d by %d\n", data.w, data.h); fflush(stdout);
g_timeout_add(3, timerEvent, &data); /* Create .003 sec timer */
gtk_main();
return (0);
}