— Gtk draggable button example c codes
示例代码如下:
命名:dragButton.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
#include <gtk/gtk.h> gboolean key_press ( GtkWidget *window, GdkEventKey *event, gpointer *data ); #define WINDATA( addr ) ( (WinData*)addr ) typedef struct WinData { gint press; gint drag; gint enter; gint width; gint height; gdouble ox, oy; /* current x,y position of button*/ gdouble cx, cy; /* current x,y position relative to the up left corner of button*/ GtkWidget *button; GtkWidget *layout; GtkWidget *window; }WinData; gboolean enter_button (GtkWidget *widget, GdkEventKey *event, gpointer *data) { //printf("Enter button\n"); WINDATA(data)->enter = 1; return TRUE; } gboolean leave_button (GtkWidget *widget, GdkEventKey *event, gpointer *data) { //printf("Leave button\n"); WINDATA(data)->enter = 0; return TRUE; } gboolean press_button (GtkWidget *widget, GdkEventKey *event, gpointer *data) { printf("Press Button\n"); WINDATA(data)->press = 1; /* 保存相对于Button本身按下的坐标位置*/ WINDATA(data)->cx = ((GdkEventMotion*)event)->x; WINDATA(data)->cy = ((GdkEventMotion*)event)->y; return TRUE; } gboolean release_button (GtkWidget *widget, GdkEventKey *event, gpointer *data) { printf("Release button\n"); WINDATA(data)->press = 0; WINDATA(data)->drag = 0; WINDATA(data)->cx = 0; WINDATA(data)->cy = 0; return TRUE; } gboolean deal_motion_notify_event ( GtkWidget *widget, GdkEventMotion *event, gpointer *data) { gdouble x = event->x; gdouble y = event->y; double offsetx; double offsety; int ax, ay; /* absolutely postition*/ int wx, wy; /* The absolutely position of the left up corner of window*/ int rx, ry; /* The position of the pointer relative to the left up corner of window*/ #if 0 /* 此段与下方未注释代码等价*/ GdkDisplay *display = gdk_display_get_default (); GdkSeat *seat = gdk_display_get_default_seat (display); GdkDevice *device = gdk_seat_get_pointer (seat); gdk_device_get_position (device, NULL, &ax, &ay); gdk_window_get_position ( gtk_widget_get_window(WINDATA(data)->window), &wx, &wy ); rx = ax - wx; ry = ay - wy; #endif gdk_window_get_position ( gtk_widget_get_window(WINDATA(data)->window), &wx, &wy ); rx = (int)event->x_root - wx; ry = (int)event->y_root - wy; gtk_window_get_size ( (GtkWindow*)WINDATA(data)->window ,\ &WINDATA(data)->width, &WINDATA(data)->height ); /* 在Button上方按下按键后使能拖拽标志位,直到释放按钮清空该标志*/ if ( WINDATA(data)->press && WINDATA(data)->enter ) WINDATA(data)->drag = 1; /* 防止超出屏幕*/ if ( rx > WINDATA(data)->width ) rx = WINDATA(data)->width ; else if ( rx <= 0 ) rx = 0; /* 防止超出屏幕*/ if ( ry > WINDATA(data)->height ) ry = WINDATA(data)->height ; else if ( ry <= 0 ) ry = 0; if ( WINDATA(data)->drag ) { gtk_layout_move ( GTK_LAYOUT(WINDATA(data)->layout), WINDATA(data)->button,\ rx-WINDATA(data)->cx, ry-WINDATA(data)->cy ); } return TRUE; } void enter_window ( GtkWidget *window, gpointer *date ) { //printf("enter window\n"); } void initWindata(WinData *win) { win->press = 0; win->cx = 0; win->cy = 0; win->button = NULL; win->layout = NULL; } int main(int argc, char **argv) { WinData win; initWindata(&win); gtk_init(&argc, &argv); win.window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size(GTK_WINDOW(win.window), 800, 600); gtk_window_set_title(GTK_WINDOW(win.window), ""); //gtk_widget_add_events(window, GDK_BUTTON_PRESS_MASK); g_signal_connect(G_OBJECT(win.window), "destroy", G_CALLBACK(gtk_main_quit),NULL); g_signal_connect(G_OBJECT(win.window), "key-press-event", G_CALLBACK(key_press),NULL); win.layout = gtk_layout_new(NULL,NULL); gtk_widget_set_size_request ( win.layout, 800, 600 ); win.button = gtk_button_new_with_label("Love"); g_signal_connect ( win.window, "enter-notify-event",G_CALLBACK(enter_window), &win); g_signal_connect ( win.button, "enter-notify-event",G_CALLBACK(enter_button), &win); g_signal_connect ( win.button, "leave-notify-event",G_CALLBACK(leave_button), &win); g_signal_connect ( win.button, "button-press-event",G_CALLBACK(press_button), &win); g_signal_connect ( win.button, "button-release-event",G_CALLBACK(release_button), &win); gtk_container_add ( GTK_CONTAINER(win.window), win.layout ); win.ox = 100, win.oy = 200; gtk_layout_put ( GTK_LAYOUT(win.layout), win.button, win.ox, win.oy ); g_signal_connect(win.window, "motion-notify-event", G_CALLBACK(deal_motion_notify_event), &win); gtk_widget_show_all(win.window); gtk_main(); return 0; } gboolean key_press ( GtkWidget *window, GdkEventKey *event, gpointer *data ) { if ( event->state == GDK_CONTROL_MASK ) { if ( event->keyval == GDK_KEY_c) { gtk_main_quit(); } } } |
代码有冗余功能,请自行截取需要使用的代码。
1 2 3 |
编译: gcc `pkg-config --cflags --libs gtk+-3.0` dragButton.c |
其中GtkLayout可以使用GtkFixed代替,但不能二者都不使用,否则Button控件直接放在window上将充满整个窗口,需要使用其他控件的原因是一个window只能放一个控件,但是GtkLayout、GtkFixed等单个控件置于window上之后,其本身可以容纳多个不同控件,因此可以作为承载Button的布局,使其在上面自由移动。