- 浏览: 444895 次
- 性别:
- 来自: 深圳
文章分类
最新评论
-
zjhgx:
多谢,多谢。多谢
Ubuntu 中软件的安装、卸载以及查看的方法总结 -
37du:
受教了,对于理解运行过程有很好的效果
ActionMapper---webwork 2.1到2.2 的变化 -
chxiaowu:
非常好,谢谢!
Ubuntu 中软件的安装、卸载以及查看的方法总结 -
euii:
谢谢,这样的总结。
Ubuntu 中软件的安装、卸载以及查看的方法总结 -
xiaoyao3857:
谢谢,正需要这样的汇总型字典!
Ubuntu 中软件的安装、卸载以及查看的方法总结
在我们教程的这一个章节中,我们会谈一谈GTK+函数工具库中的,“事件”系统 。
GTK+函数工具库是基于 “事件” 系统的。所有的 GUI 应用程序无一例外都是基于“事件”驱动的。假如没有“事件”发生,则应用程序就什么都不会做。在GTK+中一个事件就是从X窗口服务器传出来的一个消息。 当一个“事件”发生时,他就会通过发送一个“信号”来表示他已经做出了反应。利用GTK+还可以为“信号”绑定专门的回调函数。也就是说回调函数只对他特 定的“信号”才有反应并执行。
#include <gtk/gtk.h> void button_clicked(GtkWidget *widget, gpointer data) { g_print("clicked\n"); } int main( int argc, char *argv[]) { GtkWidget *window; GtkWidget *fixed; GtkWidget *button; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "GtkButton"); gtk_window_set_default_size(GTK_WINDOW(window), 230, 150); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); fixed = gtk_fixed_new(); gtk_container_add(GTK_CONTAINER(window), fixed); button = gtk_button_new_with_label("Click"); gtk_fixed_put(GTK_FIXED(fixed), button, 50, 50); gtk_widget_set_size_request(button, 80, 35); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(button_clicked), NULL); g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); gtk_widget_show_all(window); gtk_main(); return 0; }
在我们上面的这个示例应用程序中,我们有两个“信号”。一个是信号clicked ,也就是单击;另外则是信号 destroy 。
g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(button_clicked), NULL)
我们用函数 g_signal_connect() 去“连接”信号“clicked”和回调函button_clicked() 。
void button_clicked(GtkWidget *widget, gpointer data) { g_print("clicked\n"); }
这个回调函数执行的功能是向终端输出“clicked”字符串。这个函数的第一行参就是那个发射信号的对象。在我们的这个例子中实参便是构件“Click button”。第二个行参是可以选择有无的。我们可以利用这个参数向回调函数传递特定的数据。在我们的例子中,并没有传递任何的参数。所以我们就在 g_signal_connect()中调用回调函数的时候在调用的第二个实参中填上了“NULL”。
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
如果我们单击窗口右上角的“X”或者按Atl + F4, 一个destroy 就被发射出去了。然后呢,我们为这个信号所绑定的回调函数gtk_main_quit() 将执行,他的功能是终止整个应用程序。
移动窗口(Moving window)
在下一个例子中,我们将展示是如何对“移动窗口”这个事件做出反应的。
#include <gtk/gtk.h> void frame_callback(GtkWindow *window, GdkEvent *event, gpointer data) { int x, y; char buf[10]; x = event->configure.x; y = event->configure.y; sprintf(buf, "%d, %d", x, y); gtk_window_set_title(window, buf); } int main(int argc, char *argv[]) { GtkWidget *window; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_window_set_default_size(GTK_WINDOW(window), 230, 150); gtk_window_set_title(GTK_WINDOW(window), "Simple"); gtk_widget_add_events(GTK_WIDGET(window), GDK_CONFIGURE); g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), G_OBJECT(window)); g_signal_connect(G_OBJECT(window), "configure-event", G_CALLBACK(frame_callback), NULL); gtk_widget_show(window); gtk_main(); return 0; }
在这个例子中,我们随时追踪显示了位于左上角的标题栏的位置。
gtk_widget_add_events(GTK_WIDGET(window), GDK_CONFIGURE);
上面这行代码说明了,哪一个构件将回接受到事件,并对事件的发生做出反应。一些事件使用时要已与特定的构件组装好了,另外的一些事件不得不要用一个函数 gtk_widget_add_events() 去武装他。把事件类型GDK_CONFIGURE 填加到这个函数中。事件类型GDK_CONFIGURE 包含了所有的大小、位置和用于存储事件次序的栈结构。
g_signal_connect(G_OBJECT(window), "configure-event", G_CALLBACK(frame_callback), NULL);
从上面可以看出,信号“ configure-event “被发射了 ,则所绑定构件的大小、位置与次序栈都被捕获了。
void frame_callback(GtkWindow *window, GdkEvent *event, gpointer data) { int x, y; char buf[10]; x = event->configure.x; y = event->configure.y; sprintf(buf, "%d, %d", x, y); gtk_window_set_title(window, buf); }
这个回调函数有三个行参。分别是:反射信号的构件, GdkEvent 和可选择的行参.。我们获取了位置坐标(x,y),并把他放在了标题栏上。
鼠标进入信号(The enter signal)
在接下来的章节中,我们将展示如何对“鼠标的进入 ”信号作出反应。当我们的鼠标移动到我们所绑定的那个构件上时就会发出“鼠标进入信号”。
#include <gtk/gtk.h> void enter_button(GtkWidget *widget, gpointer data) { GdkColor color; color.red = 27000; color.green = 30325; color.blue = 34181; gtk_widget_modify_bg(widget, GTK_STATE_PRELIGHT, &color); } int main( int argc, char *argv[]) { GtkWidget *window; GtkWidget *fixed; GtkWidget *button; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_window_set_default_size(GTK_WINDOW(window), 230, 150); gtk_window_set_title(GTK_WINDOW(window), "enter signal"); fixed = gtk_fixed_new(); gtk_container_add(GTK_CONTAINER(window), fixed); button = gtk_button_new_with_label("Button"); gtk_widget_set_size_request(button, 80, 35); gtk_fixed_put(GTK_FIXED(fixed), button, 50, 50); g_signal_connect(G_OBJECT(button), "enter", G_CALLBACK(enter_button), NULL); g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); gtk_widget_show_all(window); gtk_main(); return 0; }
上面的程序想实现这样的一个功能:当我们的鼠标掠过按钮构件的时候,我们的程序代码可以改变那个按钮的背景颜色。
g_signal_connect(G_OBJECT(button), "enter", G_CALLBACK(enter_button), NULL);
当信号“enter ”发生时,我们会调用函数 enter_button()
GdkColor color; color.red = 27000; color.green = 30325; color.blue = 34181; gtk_widget_modify_bg(widget, GTK_STATE_PRELIGHT, &color);
在对应的回调函数中,我们通过调用函数gtk_widget_modify_bg() 来改变按钮的颜色。
回调函数解除绑定(Disconnecting a callback)
既然可以为一个信号绑定一个回调函数,我们当然也可以解除一个绑定。在接下来的代码示范示例中就是这样的一个例子。
#include <gtk/gtk.h> int handler_id; void button_clicked(GtkWidget *widget, gpointer data) { g_print("clicked\n"); } void toogle_signal(GtkWidget *widget, gpointer window) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { handler_id = g_signal_connect(G_OBJECT(window), "clicked", G_CALLBACK(button_clicked), NULL); } else { g_signal_handler_disconnect(window, handler_id); } } int main( int argc, char *argv[]) { GtkWidget *window; GtkWidget *fixed; GtkWidget *button; GtkWidget *check; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_window_set_default_size(GTK_WINDOW(window), 250, 150); gtk_window_set_title(GTK_WINDOW(window), "Disconnect"); fixed = gtk_fixed_new(); gtk_container_add(GTK_CONTAINER(window), fixed); button = gtk_button_new_with_label("Click"); gtk_widget_set_size_request(button, 80, 30); gtk_fixed_put(GTK_FIXED(fixed), button, 30, 50); check = gtk_check_button_new_with_label("Connect"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE); gtk_fixed_put(GTK_FIXED(fixed), check, 130, 50); handler_id = g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(button_clicked), NULL); g_signal_connect(G_OBJECT(check), "clicked", G_CALLBACK(toogle_signal), (gpointer) button); g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); gtk_widget_show_all(window); gtk_main(); return 0; }
在例子中,我们生成了一个按钮和一个选择框。那个选择框的功能便是绑定或者解除绑定一个回调函数与信号“clicked”之间的关系。
handler_id = g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(button_clicked), NULL);
g_signal_connect() 函数执行后会返回一个“id”数据。这就是实现了对回调函数的唯一标示。
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { handler_id = g_signal_connect(G_OBJECT(window), "clicked", G_CALLBACK(button_clicked), NULL); } else { g_signal_handler_disconnect(window, handler_id); }
这段代码决定了选择框的状态,如果选中了,就绑定否则就解除绑定。
(拖与放的示例)Drag and Drop example
在接下一个示例中,我们将展示一个有趣的特性。我们将生成一个没有边框的窗口,然后我们将说明如何才能拖动和放置这样的一个窗口。
#include <gtk/gtk.h> gboolean on_button_press (GtkWidget* widget, GdkEventButton * event, GdkWindowEdge edge) { if (event->type == GDK_BUTTON_PRESS) { if (event->button == 1) { gtk_window_begin_move_drag(GTK_WINDOW(gtk_widget_get_toplevel(widget)), event->button, event->x_root, event->y_root, event->time); } } return FALSE; } int main( int argc, char *argv[]) { GtkWidget *window; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_window_set_default_size(GTK_WINDOW(window), 230, 150); gtk_window_set_title(GTK_WINDOW(window), "Drag & drop"); gtk_window_set_decorated(GTK_WINDOW (window), FALSE); gtk_widget_add_events(window, GDK_BUTTON_PRESS_MASK); g_signal_connect(G_OBJECT(window), "button-press-event", G_CALLBACK(on_button_press), NULL); g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), G_OBJECT(window)); gtk_widget_show(window); gtk_main(); return 0; }
上面的这个示例程序向我们展示了如何才能生成一个可以拖拉和放置的无边框的窗口程序。
gtk_window_set_decorated(GTK_WINDOW (window), FALSE);
我们去除了窗口中的一些修饰性的部分。也就是说我们的这个窗口没有边框和标题栏。
g_signal_connect(G_OBJECT(window), "button-press-event", G_CALLBACK(on_button_press), NULL);
我们把信号button-press-event 绑定在窗口中。
gboolean on_button_press (GtkWidget* widget, GdkEventButton * event, GdkWindowEdge edge) { if (event->type == GDK_BUTTON_PRESS) { if (event->button == 1) { gtk_window_begin_move_drag(GTK_WINDOW(gtk_widget_get_toplevel(widget)), event->button, event->x_root, event->y_root, event->time); } } return FALSE; }
在回调函数on_button_press() 中,我们放置了拖动和放置的代码。 我们检测是否鼠标被单击(左击)。然后条件判断执行函数 gtk_window_begin_move_drag() 进行拖放操作。
(一个定时器) A timer example
在接下来的示例中我们将向你展示如何去生成一个定时器。定时器通常应用于当我们要做一些重复工作的场合。譬如一个时钟,一个倒记时和增加动态的视觉效应。
#include <cairo.h> #include <gtk/gtk.h> #include <time.h> static char buffer[256]; static gboolean on_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer data) { cairo_t *cr; cr = gdk_cairo_create(widget->window); cairo_move_to(cr, 30, 30); cairo_show_text(cr, buffer); cairo_destroy(cr); return FALSE; } static gboolean time_handler(GtkWidget *widget) { if (widget->window == NULL) return FALSE; time_t curtime; struct tm *loctime; curtime = time(NULL); loctime = localtime(&curtime); strftime(buffer, 256, "%T", loctime); gtk_widget_queue_draw(widget); return TRUE; } int main (int argc, char *argv[]) { GtkWidget *window; GtkWidget *darea; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); darea = gtk_drawing_area_new(); gtk_container_add(GTK_CONTAINER (window), darea); g_signal_connect(darea, "expose-event", G_CALLBACK(on_expose_event), NULL); g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_window_set_default_size(GTK_WINDOW(window), 170, 100); gtk_window_set_title(GTK_WINDOW(window), "timer"); g_timeout_add(1000, (GSourceFunc) time_handler, (gpointer) window); gtk_widget_show_all(window); time_handler(window); gtk_main(); return 0; }
我们将要在窗口中,“画”一个显示当前时间的动态效果。所用的工具,就是在我们一开始曾经提到过的Cairo函数工具库。
g_signal_connect(darea, "expose-event", G_CALLBACK(on_expose_event), NULL);
首先我们要把在回调函数 on_expose_event() 中画出时间的数值。这个回调函数与信号进行了绑定expose-event 。如果这个信号发射出去了,这个窗口就会按照我们程序所安排的一样——“立即刷新”。
g_timeout_add(1000, (GSourceFunc) time_handler, (gpointer) window);
上面的这个函数注册了一个GTK+系统中的一个定时器(是抽象的不可见的)。函数 time_handler() 就会被按照我们在函数中的设置在设定的时间内不断的运行。在例子中,我们设定了这个时间为1秒,一旦这个函数 g_timeout_add() 返回FALSE,定时器函数 time_handler() 就会运行。
time_handler(window);
这行代码的作用是立即启动定时器,否则的话,你会看到1秒的延迟。
cairo_t *cr; cr = gdk_cairo_create(widget->window); cairo_move_to(cr, 30, 30); cairo_show_text(cr, buffer); cairo_destroy(cr);
以上便是用来在当前窗口上画出当前时间的代码。如果你想了解更多的关于Cairo函数库的一些情况请访问 版权属于ZetCode。. .
if (widget->window == NULL) return FALSE;
在我们刷新窗口前,很显然要先注销窗口,这样的话,定时函数便被自动调用了;可当我们关闭窗口时,定时器也会被调用,这是我们不想看到了,所以需要加上以上的代码,阻止在已经关闭的构件上运行定时器。
time_t curtime; struct tm *loctime; curtime = time(NULL); loctime = localtime(&curtime); strftime(buffer, 256, "%T", loctime);
上面的代码获取了系统当前的时间。
gtk_widget_queue_draw(widget);
这段代码会注销窗口,然后信号 expose-event 就会被激活发射出去。从而被绑定的回调函数就会执行。
发表评论
-
htonl(),htons(),ntohl(),ntons()--大小端模式转换函数
2010-12-16 16:51 4053不同机器内部对变量的字节存储顺序不同,有的采用大端模式(big ... -
关于Linux静态库和动态库的分析
2010-09-28 10:29 16151.什么是库在windows平台和linux平台下都大量存在着 ... -
Heartbeat
2010-09-01 19:31 1379Heartbeat 项目是 Linux-HA ... -
linux下更改共享内存的最大值
2010-07-26 13:22 6031System V IPC 参数 名字 ... -
环境变量相关
2010-06-10 15:03 979系统环境变量: /etc/profile:此文件 ... -
linux中的信号处理(signal与alarm)
2010-05-12 15:25 1769简单处理程序: ... -
LINUX 时间和日期
2010-04-01 19:09 2549时间与日期 通常对于 一个程序来说可以确定时间与日期是十分 ... -
IPC之消息队列
2010-03-13 12:05 1409消息队列缺点: 1. 如果进程创建了一个消息队列,在该队 ... -
如何让errno多线程/进程安全
2010-03-13 11:35 1758在 linux 或者 unix 环境中, errno ... -
Linux下库相关的概略介绍及动态库的搜索路径优先级
2010-03-13 11:29 1625(本文主要针对动态连接 ... -
ftok函数
2010-03-13 11:01 1745系统建立IPC通讯(如消 ... -
About pci.ids
2009-12-23 21:01 1726pci.ids - This is a public r ... -
port I/O
2009-12-21 15:27 1156Name outb, outw, outl, outsb ... -
udev相关
2009-12-11 20:22 1166udev 是Linux kernel 2.6系 ... -
SMP(Symmetrical Multi-Processing)
2009-12-11 15:22 1732对称多处理" ... -
功能强大的sed命令
2009-11-27 21:55 2004vim不太熟练,发现shell的sed命令很强大。 1. S ... -
/etc/sudoers配置文件的格式
2009-11-25 20:56 1614-------下面文章转载自网 ... -
/etc/sudoers中的含义
2009-11-25 20:55 2485Sudo 是允许系统管理员让普通用户执行一些或者全部的roo ... -
linux下如何模拟按键输入和模拟鼠标
2009-11-14 10:06 2815查看/dev/input/eventX是什么类型的事件, ca ... -
Linux root file system
2009-11-05 20:03 10591. Linux for PowerPC Embedded S ...
相关推荐
GTK+ 参考手册 for GTK+ 2.14.3,最新英文版 GTK+ is a library for creating graphical user interfaces. It works on many UNIX-like platforms, Windows, and on framebuffer devices. GTK+ is released under ...
Foundations of GTK+ Development (PDF 英文版) By Andrew Krause ISBN10: 1-59059-793-1 ISBN13: 978-1-59059-793-4 630 pages Apr 2007 (Apress) GTK+ is one of the most influential graphical toolkits for...
基于C gtk/gtk+ sqlite3选课系统的开发
gtk+开发工具gtk+开发工具gtk+开发工具
GTK+程序设计中文版 .pdf
最新的基于GTK+的单词数值计算器基于linux开发,中文显示,见面优化,配带有相关文件,流程图,代码
GTK+2.0编程范例-书籍和书中代码.tar.gz GTK+2.0编程范例 书本比较清晰 加上有代码 GTK入门和提高必备
GTK+(GIMP Toolkit)是一套跨多种平台的图形工具包,按LGPL许可协议发布的。虽然最初是为GIMP写的,但目前已发展为一...可以把 GTK+ 想像成一个工具包,从这个工具包中可以找到用来创建 GUI 的许多已经准备好的构造块。
gtk+-bundle_2.18.7-20100213_win32 gtk+-bundle_2.18.7-20100213_win32
gtk+-2.24.0.tar.bz2 GTK+源代码 自己需要的
压缩包包含gtk+-bundle_2.24.10-20120208_win32文件和gtk+ Visual Studio 2008环境搭建文档说明
本书详细介绍了两种Linux图形用户界面开发技术:GTK+/GNOME。主要内容包括:GUI的基本概念,GLib,GTK+及GNOME的...本书虽然适合GTK+和GNOME编程的初学者学习,但不管是程序设计新手还是编程专家,都能从本书中获益。
GTK+虽然是Linux下的开发工具包,但是因为其跨平台特性,我们可能需要在Windows 环境下进行程序开发。所以如何在Windows下配置GTK+的开发环境,是许多Gtk学习者的实际需求。 本文在下文基础上增加了GTK+3.0模板修改...
英文名称:The GTK+ tutorial 本GTK+程序初级教程采用了“引导”式的方法来教你如何使用GTK+。本教程所用的编程语言为C语言。并且整个教程中方法已经在Linux中测试通过。本教程适用GTK+的初级兼代中级水平的程序员...
GTK+是一个跨平台开源GUI图形界面库,本资源是用在Windows上面的版本
注意: GTK+ 3.x版本跟Python2.7不兼容,如果在Python下使用GTK,需要安装2.x版的gtk+ (在windows上如此)
PDF电子书《用GTK+和GDK开发Linux图形用户界面应用》
第五部分包括三个附录,附录A是书中使用的示例GnomeHello的源代码,附录B介绍了一些与Gtk+/Gnome编程相关的在线资源,附录C是Gtk+/Gnome对象的简要介绍。本书中的Gtk+构件示例都来自于GTK 1.2.3软件包的示例。如果...
5.8 信号和事件有什么区别? 5.9 我的delete_event (或者是其他事件)操作函数得到了错误的参数。 5.10 我已经联结了事件处理函数,但是这个好像没有起作用,那个地方错了? 5.11 我怎么增加一个新的信号到一个GTK+ ...