gtk界面设计
一。GTK基本
#include <gtk/gtk.h>
int main( int argc, char *argv[])
{
GtkWidget *window;
/*初始化整个GTK+程序,是每一个GTK+程序必不可少的部分*/
gtk_init(&argc, &argv);
/*这里生成了一个窗口构件——GtkWindow,GTK_WINDOW_TOPLEVEL包含窗口的标题栏和边框,同意用窗口管理器来进行管理*/
window = gtk_window_new(GTK_WINDOW_TOPLEVEL); /*开始显示窗口*/
gtk_widget_show(window);
gtk_main();
return ;
}
二。显示窗口和调整窗口
#include <gtk/gtk.h>
int main( int argc, char *argv[])
{
GtkWidget *window;
/*初始化整个GTK+程序,是每一个GTK+程序必不可少的部分*/
gtk_init(&argc, &argv);
/*这里生成了一个窗口构件——GtkWindow,GTK_WINDOW_TOPLEVEL包含窗口的标题栏和边框,同意用窗口管理器来进行管理*/
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
/*设置窗口标题*/
gtk_window_set_title(GTK_WINDOW(window), "机器人");
/*设置窗口默认大小*/
gtk_window_set_default_size(GTK_WINDOW(window), , );
/*
* 设置窗口在显示器中的位置为居中。
* GTK_WIN_POS_NONE :不固定
* GTK_WIN_POS_CENTER : 居中
* GTK_WIN_POS_MOUSE : 出现在鼠标位置
* GTK_WIN_POS_CENTER_ALWAYS : 窗口改变大小的时候仍然居中
*/
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); /*开始显示窗口*/
gtk_widget_show(window);
gtk_main();
return ;
}
三。设置应用程序的图标
#include <gtk/gtk.h> GdkPixbuf *create_pixbuf(const gchar * filename)
{
GdkPixbuf *pixbuf;
GError *error = NULL;
/*
* 函数gdk_pixbuf_new_from_file() 从一个图片文件中加载图象数据,从而生成一个新的 pixbuf,
* 至于文件中包含图象的格式,是由系统自动检测的。如果该函数返回值是NULL 的话,程序就会出现错误。
*/
pixbuf = gdk_pixbuf_new_from_file(filename, &error);
if(!pixbuf) {
fprintf(stderr, "%s\n", error->message);
g_error_free(error);
}
return pixbuf;
} int main( int argc, char *argv[])
{
GtkWidget *window;
/*初始化整个GTK+程序,是每一个GTK+程序必不可少的部分*/
gtk_init(&argc, &argv);
/*这里生成了一个窗口构件——GtkWindow,GTK_WINDOW_TOPLEVEL包含窗口的标题栏和边框,同意用窗口管理器来进行管理*/
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
/*设置窗口标题*/
gtk_window_set_title(GTK_WINDOW(window), "科希机器人-小希");
/*设置窗口默认大小*/
gtk_window_set_default_size(GTK_WINDOW(window), , );
/*
* 设置窗口在显示器中的位置为居中。
* GTK_WIN_POS_NONE :不固定
* GTK_WIN_POS_CENTER : 居中
* GTK_WIN_POS_MOUSE : 出现在鼠标位置
* GTK_WIN_POS_CENTER_ALWAYS : 窗口改变大小的时候仍然居中
*/
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); /*函数gtk_window_set_icon() 是为窗口设置图标用的,函数create_pixbuf是我们自定义的,目的是从一个图片中获取信息得到pixbuf。*/
gtk_window_set_icon(GTK_WINDOW(window), create_pixbuf(argv[])); /*开始显示窗口*/
gtk_widget_show(window);
gtk_main();
return ;
}
四。当点击关闭窗口(X)时,应该结束程序
在命令行下运行这个demo,点击右上角的X时候,窗口虽然关闭了,但是程序还在运行,需要按ctrl+C(linux下 ctrl+D)来结束程序运行。我们希望点击X的时候就结束程序的运行。我们必须要明确为这个例子程序连接一个关闭的信号(destroy signal),然后调用回调函数gtk_main_quit() 实现结束程序。这里涉及到事件和信号会在日后讲到。
#include <gtk/gtk.h> /*
@Description: 从一个图片中获取信息得到pixbuf
@param: gchar filename
*/
GdkPixbuf *create_pixbuf(const gchar * filename)
{
GdkPixbuf *pixbuf;
GError *error = NULL;
/*
* 函数gdk_pixbuf_new_from_file() 从一个图片文件中加载图象数据,从而生成一个新的 pixbuf,
* 至于文件中包含图象的格式,是由系统自动检测的。如果该函数返回值是NULL 的话,程序就会出现错误。
*/
pixbuf = gdk_pixbuf_new_from_file(filename, &error);
if(!pixbuf) {
fprintf(stderr, "%s\n", error->message);
g_error_free(error);
}
return pixbuf;
} int main( int argc, char *argv[])
{
GtkWidget *window;
/*初始化整个GTK+程序,是每一个GTK+程序必不可少的部分*/
gtk_init(&argc, &argv);
/*这里生成了一个窗口构件——GtkWindow,GTK_WINDOW_TOPLEVEL包含窗口的标题栏和边框,同意用窗口管理器来进行管理*/
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
/*设置窗口标题*/
gtk_window_set_title(GTK_WINDOW(window), "机器人");
/*设置窗口默认大小*/
gtk_window_set_default_size(GTK_WINDOW(window), , );
/*
* 设置窗口在显示器中的位置为居中。
* GTK_WIN_POS_NONE :不固定
* GTK_WIN_POS_CENTER : 居中
* GTK_WIN_POS_MOUSE : 出现在鼠标位置
* GTK_WIN_POS_CENTER_ALWAYS : 窗口改变大小的时候仍然居中
*/
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); /*函数gtk_window_set_icon() 是为窗口设置图标用的,函数create_pixbuf是我们自定义的,目的是从一个图片中获取信息得到pixbuf。*/
gtk_window_set_icon(GTK_WINDOW(window), create_pixbuf(argv[])); /***********************************以下是信号处理部分************************************/ /*关闭窗口时退出主循环*/
g_signal_connect_swapped(G_OBJECT(window),"destroy",G_CALLBACK(gtk_main_quit), NULL); /***********************************以下是显示控件部分************************************/
/*开始显示窗口*/
gtk_widget_show(window); gtk_main();
return ;
}
五。添加简单菜单栏,以后在逐步完善
#include <gtk/gtk.h> /*
@Description: 从一个图片中获取信息得到pixbuf
@param: gchar filename
*/
GdkPixbuf *create_pixbuf(const gchar * filename)
{
GdkPixbuf *pixbuf;
GError *error = NULL;
/*
* 函数gdk_pixbuf_new_from_file() 从一个图片文件中加载图象数据,从而生成一个新的 pixbuf,
* 至于文件中包含图象的格式,是由系统自动检测的。如果该函数返回值是NULL 的话,程序就会出现错误。
*/
pixbuf = gdk_pixbuf_new_from_file(filename, &error);
if(!pixbuf) {
fprintf(stderr, "%s\n", error->message);
g_error_free(error);
}
return pixbuf;
} int main( int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *vbox; //盒装容器
GtkWidget *menubar; //菜单栏
GtkWidget *menutoggle, *menu_tog_toggle,*menu_tog_toolbar, *menu_tog_statusbar; //界面开关菜单
//GtkWidget *menu_about, *menu_about_us; //帮助菜单 /*初始化整个GTK+程序,是每一个GTK+程序必不可少的部分*/
gtk_init(&argc, &argv);
/*这里生成了一个窗口构件——GtkWindow,GTK_WINDOW_TOPLEVEL包含窗口的标题栏和边框,同意用窗口管理器来进行管理*/
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
/*设置窗口标题*/
gtk_window_set_title(GTK_WINDOW(window), "小希机器人");
/*设置窗口默认大小*/
gtk_window_set_default_size(GTK_WINDOW(window), , );
/*
* 设置窗口在显示器中的位置为居中。
* GTK_WIN_POS_NONE :不固定
* GTK_WIN_POS_CENTER : 居中
* GTK_WIN_POS_MOUSE : 出现在鼠标位置
* GTK_WIN_POS_CENTER_ALWAYS : 窗口改变大小的时候仍然居中
*/
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); /*函数gtk_window_set_icon() 是为窗口设置图标用的,函数create_pixbuf是我们自定义的,目的是从一个图片中获取信息得到pixbuf。*/
gtk_window_set_icon(GTK_WINDOW(window), create_pixbuf("/home/zxwbot/Pictures/1.jpg")); /*创建一个盒装容器并添加到窗口中*/
vbox = gtk_vbox_new(FALSE, );
gtk_container_add(GTK_CONTAINER(window), vbox); /*创建菜单*/
menubar = gtk_menu_bar_new(); //代表整个菜单,是一个menu shell menutoggle = gtk_menu_new(); //这里代表第一列菜单toggle ,也是一个menu shell
menu_tog_toggle = gtk_menu_item_new_with_label("导航");
menu_tog_toolbar = gtk_menu_item_new_with_label("创建地图"); //toggle 菜单中子项
menu_tog_statusbar = gtk_menu_item_new_with_label("清除地图"); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_tog_toggle), menutoggle); //widget toggle菜单加入 menutoggle menu shell
gtk_menu_shell_append(GTK_MENU_SHELL(menutoggle), menu_tog_toolbar);
gtk_menu_shell_append(GTK_MENU_SHELL(menutoggle), menu_tog_statusbar); gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menu_tog_toggle); /*把菜单加入盒子容器*/
gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, );
/***********************************以下是信号处理部分************************************/ /*关闭窗口时退出主循环*/
g_signal_connect_swapped(G_OBJECT(window),"destroy",G_CALLBACK(gtk_main_quit), NULL); /***********************************以下是显示控件部分************************************/
/*开始显示窗口*/
//gtk_widget_show(window);
gtk_widget_show_all(window); gtk_main();
return ;
}
六。添加状态栏,并点击任意菜单的时候在状态来显示内容
#include <gtk/gtk.h> /*
@Description: 从一个图片中获取信息得到pixbuf
@param: gchar filename
*/
GdkPixbuf *create_pixbuf(const gchar * filename)
{
GdkPixbuf *pixbuf;
GError *error = NULL;
/*
* 函数gdk_pixbuf_new_from_file() 从一个图片文件中加载图象数据,从而生成一个新的 pixbuf,
* 至于文件中包含图象的格式,是由系统自动检测的。如果该函数返回值是NULL 的话,程序就会出现错误。
*/
pixbuf = gdk_pixbuf_new_from_file(filename, &error);
if(!pixbuf) {
fprintf(stderr, "%s\n", error->message);
g_error_free(error);
}
return pixbuf;
} /*点击菜单时,状态栏显示*/
void menu_pressed(GtkWidget *widget, gpointer window)
{
gchar *str;
str = g_strdup_printf("you clicked one menu item");
gtk_statusbar_push(GTK_STATUSBAR(window),gtk_statusbar_get_context_id(GTK_STATUSBAR(window), str), str);
g_free(str);
} int main( int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *vbox; //盒装容器
GtkWidget *menubar; //菜单栏
GtkWidget *menutoggle, *menu_tog_toggle,*menu_tog_toolbar, *menu_tog_statusbar; //界面开关菜单
//GtkWidget *menu_about, *menu_about_us; //帮助菜单
GtkWidget *statusbar; //状态栏 /*初始化整个GTK+程序,是每一个GTK+程序必不可少的部分*/
gtk_init(&argc, &argv);
/*这里生成了一个窗口构件——GtkWindow,GTK_WINDOW_TOPLEVEL包含窗口的标题栏和边框,同意用窗口管理器来进行管理*/
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
/*设置窗口标题*/
gtk_window_set_title(GTK_WINDOW(window), "机器人");
/*设置窗口默认大小*/
gtk_window_set_default_size(GTK_WINDOW(window), , );
/*
* 设置窗口在显示器中的位置为居中。
* GTK_WIN_POS_NONE :不固定
* GTK_WIN_POS_CENTER : 居中
* GTK_WIN_POS_MOUSE : 出现在鼠标位置
* GTK_WIN_POS_CENTER_ALWAYS : 窗口改变大小的时候仍然居中
*/
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); /*函数gtk_window_set_icon() 是为窗口设置图标用的,函数create_pixbuf是我们自定义的,目的是从一个图片中获取信息得到pixbuf。*/
gtk_window_set_icon(GTK_WINDOW(window), create_pixbuf(argv[])); /*创建一个盒装容器并添加到窗口中*/
vbox = gtk_vbox_new(FALSE, );
gtk_container_add(GTK_CONTAINER(window), vbox); /*创建菜单*/
menubar = gtk_menu_bar_new(); //代表整个菜单,是一个menu shell menutoggle = gtk_menu_new(); //这里代表第一列菜单toggle ,也是一个menu shell
menu_tog_toggle = gtk_menu_item_new_with_label("导航");
menu_tog_toolbar = gtk_menu_item_new_with_label("清除地图"); //toggle 菜单中子项
menu_tog_statusbar = gtk_menu_item_new_with_label("创建地图"); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_tog_toggle), menutoggle); //widget toggle菜单加入 menutoggle menu shell
gtk_menu_shell_append(GTK_MENU_SHELL(menutoggle), menu_tog_toolbar);
gtk_menu_shell_append(GTK_MENU_SHELL(menutoggle), menu_tog_statusbar); gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menu_tog_toggle); /*把菜单加入盒子容器*/
gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, ); statusbar = gtk_statusbar_new();
gtk_box_pack_end(GTK_BOX(vbox), statusbar, FALSE, TRUE, );
/***********************************以下是信号处理部分************************************/ /*关闭窗口时退出主循环*/
g_signal_connect_swapped(G_OBJECT(window),"destroy",G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(G_OBJECT(menu_tog_toolbar),"activate",G_CALLBACK(menu_pressed), G_OBJECT(statusbar));
g_signal_connect(G_OBJECT(menu_tog_statusbar),"activate",G_CALLBACK(menu_pressed), G_OBJECT(statusbar)); /***********************************以下是显示控件部分************************************/
/*开始显示窗口*/
//gtk_widget_show(window);
gtk_widget_show_all(window); gtk_main();
return ;
}
七。添加工具栏,并给“退出”按钮加入信号
#include <gtk/gtk.h> /*
@Description: 从一个图片中获取信息得到pixbuf
@param: gchar filename
*/
GdkPixbuf *create_pixbuf(const gchar * filename)
{
GdkPixbuf *pixbuf;
GError *error = NULL;
/*
* 函数gdk_pixbuf_new_from_file() 从一个图片文件中加载图象数据,从而生成一个新的 pixbuf,
* 至于文件中包含图象的格式,是由系统自动检测的。如果该函数返回值是NULL 的话,程序就会出现错误。
*/
pixbuf = gdk_pixbuf_new_from_file(filename, &error);
if(!pixbuf) {
fprintf(stderr, "%s\n", error->message);
g_error_free(error);
}
return pixbuf;
} /*点击菜单时,状态栏显示*/
void menu_pressed(GtkWidget *widget, gpointer window)
{
gchar *str;
str = g_strdup_printf("you click one menu item");
gtk_statusbar_push(GTK_STATUSBAR(window),gtk_statusbar_get_context_id(GTK_STATUSBAR(window), str), str);
g_free(str);
} int main( int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *vbox; //盒装容器
GtkWidget *menubar; //菜单栏
GtkWidget *menutoggle, *menu_tog_toggle,*menu_tog_toolbar, *menu_tog_statusbar; //界面开关菜单
//GtkWidget *menu_about, *menu_about_us; //帮助菜单
GtkWidget *toolbar; //工具栏
GtkToolItem *tool_exit, *tool_sep,*tool_about;
GtkWidget *statusbar; //状态栏 /*初始化整个GTK+程序,是每一个GTK+程序必不可少的部分*/
gtk_init(&argc, &argv);
/*这里生成了一个窗口构件——GtkWindow,GTK_WINDOW_TOPLEVEL包含窗口的标题栏和边框,同意用窗口管理器来进行管理*/
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
/*设置窗口标题*/
gtk_window_set_title(GTK_WINDOW(window), "机器人");
/*设置窗口默认大小*/
gtk_window_set_default_size(GTK_WINDOW(window), , );
/*
* 设置窗口在显示器中的位置为居中。
* GTK_WIN_POS_NONE :不固定
* GTK_WIN_POS_CENTER : 居中
* GTK_WIN_POS_MOUSE : 出现在鼠标位置
* GTK_WIN_POS_CENTER_ALWAYS : 窗口改变大小的时候仍然居中
*/
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); /*函数gtk_window_set_icon() 是为窗口设置图标用的,函数create_pixbuf是我们自定义的,目的是从一个图片中获取信息得到pixbuf。*/
gtk_window_set_icon(GTK_WINDOW(window), create_pixbuf(argv[])); /*创建一个盒装容器并添加到窗口中*/
vbox = gtk_vbox_new(FALSE, );
gtk_container_add(GTK_CONTAINER(window), vbox); /*创建菜单*/
menubar = gtk_menu_bar_new(); //代表整个菜单,是一个menu shell menutoggle = gtk_menu_new(); //这里代表第一列菜单toggle ,也是一个menu shell
menu_tog_toggle = gtk_menu_item_new_with_label("View");
menu_tog_toolbar = gtk_menu_item_new_with_label("show Toolbar"); //toggle 菜单中子项
menu_tog_statusbar = gtk_menu_item_new_with_label("show Statusbar"); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_tog_toggle), menutoggle); //widget toggle菜单加入 menutoggle menu shell
gtk_menu_shell_append(GTK_MENU_SHELL(menutoggle), menu_tog_toolbar);
gtk_menu_shell_append(GTK_MENU_SHELL(menutoggle), menu_tog_statusbar); gtk_menu_shell_append(GTK_MENU_SHELL(menubar), menu_tog_toggle); //创建工具栏
toolbar = gtk_toolbar_new();
gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS); //设置工具栏样式为图标
gtk_container_set_border_width(GTK_CONTAINER(toolbar), ); //工具栏边框大小 tool_exit = gtk_tool_button_new_from_stock(GTK_STOCK_QUIT); //工具栏中的 “退出” 按钮
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tool_exit, -); tool_sep = gtk_separator_tool_item_new(); //工具栏中按钮之间的分割线
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tool_sep, -); tool_about = gtk_tool_button_new_from_stock(GTK_STOCK_HELP); //工具栏中的“关于” 按钮
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tool_about, -); statusbar = gtk_statusbar_new();
/*把菜单加入盒子容器*/
gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, );
/*把工具栏加入盒子容器*/
gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, );
/*把状态栏加入盒子最下面*/
gtk_box_pack_end(GTK_BOX(vbox), statusbar, FALSE, TRUE, ); /***********************************以下是信号处理部分************************************/
/*关闭窗口时退出主循环*/
g_signal_connect_swapped(G_OBJECT(window),"destroy",G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(G_OBJECT(tool_exit), "clicked",G_CALLBACK(gtk_main_quit), NULL); g_signal_connect(G_OBJECT(menu_tog_toolbar),"activate",G_CALLBACK(menu_pressed), G_OBJECT(statusbar));
g_signal_connect(G_OBJECT(menu_tog_statusbar),"activate",G_CALLBACK(menu_pressed), G_OBJECT(statusbar)); /***********************************以下是显示控件部分************************************/
/*开始显示窗口*/
//gtk_widget_show(window);
gtk_widget_show_all(window); gtk_main();
return ;
}
八。窗口背景设置
#include <gtk/gtk.h> /* 功能: 设置背景图
* widget: 主窗口
* w, h: 图片的大小
* path: 图片路径
*/
void chang_background(GtkWidget *widget, int w, int h, const gchar *path)
{
gtk_widget_set_app_paintable(widget, TRUE); //允许窗口可以绘图
gtk_widget_realize(widget); /* 更改背景图时,图片会重叠
* 这时要手动调用下面的函数,让窗口绘图区域失效,产生窗口重绘制事件(即 expose 事件)。
*/
gtk_widget_queue_draw(widget); GdkPixbuf *src_pixbuf = gdk_pixbuf_new_from_file(path, NULL); // 创建图片资源对象
// w, h是指定图片的宽度和高度
GdkPixbuf *dst_pixbuf = gdk_pixbuf_scale_simple(src_pixbuf, w, h, GDK_INTERP_BILINEAR); GdkPixmap *pixmap = NULL; /* 创建pixmap图像;
* NULL:不需要蒙版;
* 123: 0~255,透明到不透明
*/
gdk_pixbuf_render_pixmap_and_mask(dst_pixbuf, &pixmap, NULL, );
// 通过pixmap给widget设置一张背景图,最后一个参数必须为: FASLE
gdk_window_set_back_pixmap(widget->window, pixmap, FALSE); // 释放资源
g_object_unref(src_pixbuf);
g_object_unref(dst_pixbuf);
g_object_unref(pixmap);
} int main( int argc, char *argv[])
{
gtk_init(&argc, &argv); //主窗口操作
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "设置窗口背景图");
gtk_widget_set_size_request(window, , ); chang_background(window, , , argv[]); // 设置窗口背景图 gtk_widget_show_all(window); // 显示所有部件 gtk_main(); return ;
}
九。
绘图事件
GTK界面只要有图片的地方,其底层实际上是通过绘图实现的,所以,我们很有必要学习一下绘图,这里我们使用 Cairo 进行相应的绘图操作。
Cairo是用于绘制二维矢量图形的跨平台图形库,采用 C
语言实现,又被许多其它计算机语言所绑定。我们可以使用Cairo库在窗口中绘图,也可以用于生成PNG图片、PDF、PostScript、SVG文件。Cairo同时也是自由软件库,自GTK+2.8版本开始,Cairo成为GTK+库的一部分。
绘图实际上也是事件的一种,GTK中,绘图事件也叫曝光事件。
绘图时所触发的信号:expose-event
只要触发曝光事件信号"expose-event",就会自动调用所连接的回调函数。
这里需要注意的是,曝光事件信号 "expose-event"
默认的情况下,是自动触发的(当然也可以人为触发),就算我们不作任何操作,"expose-event"信号也有可能自动触发。前面我们学习中,我们按一下按钮就人为触发
"clicked" 信号,按一下鼠标人为触发 "button-press-event"
信号,如果我们不操作按钮,不操作鼠标,其对应的信号永远不会触发。
曝光事件信号 "expose-event" 什么时候会自动触发呢?
窗口状态(移动,初始化,按按钮……)改变,只用我们肉眼能看到窗口上有变化,它都会自动触发曝光事件信号"expose-event",然后就自动会调用它所连接的回调函数,但是,它不是刷新窗口的全部区域,它是按需要局部刷新,哪儿变化了就刷新那个变化的区域。
当然我们也可以人为触发曝光事件信号"expose-event",并且指定刷图区域:
触发信号,并且刷新图片的整个区域:
void gtk_widget_queue_draw(GtkWidget *widget );
widget:控件指针
触发信号,并指定刷图区域:
void gtk_widget_queue_draw_area(
GtkWidget *widget,
gint x,
gint y,
gint width,
gint height);
widget:控件指针
x, y:刷图的起点坐标
width, height:刷图的宽、高
需要注意的是,我们绘图的操作不是写在任何函数都行,尽量在曝光事件信号 "expose-event" 所连接的回调函数里进行相应的绘图操作。
gboolean callback( GtkWidget *widget,
GdkEventExpose *event,
gpointer data )
{
// 绘图的相关操作
…… return FALSE; // 尽量返回FALSE
}
如果窗口里有其它控件,回调函数必须返回FALSE,否则窗口里的控件会被绘图覆盖。
使用 Cairo , 需要包含的头文件:#include <cairo.h>。
创建Cairo环境:
cairo_t *gdk_cairo_create( GdkDrawable *drawable );
drawable:绘图区域
返回值:cairo绘图环境指针
注意:如果给窗口绘图,窗口本身不能绘图,窗口本质上是一个结构体,里面有个window成员,这个window成员才是真正的绘图区域。
如:
GtkWidget *w = gtk_window_new( GTK_WINDOW_TOPLEVEL );
cairo_t *cr = gdk_cairo_create(w->window); // 注意传的参数
回收资源:
void cairo_destroy(cairo_t *cr);
参数:cairo绘图环境指针
设置画图的图片:
void gdk_cairo_set_source_pixbuf(
cairo_t *cr,
const GdkPixbuf *pixbuf,
double pixbuf_x,
double pixbuf_y );
cr:cairo绘图环境指针
pixbuf:图片资源对象
pixbuf_x,pixbuf_y:画图的起点位置
绘制设置好的图片:
void cairo_paint(cairo_t *cr);
cr:cairo绘图环境指针
注意:如果绘制图片后想继续写字或画线,必须手动设置画笔颜色( cairo_set_source_rgb() ), 否则,字体或线条会被图片覆盖。
如果在窗口上绘图,要设置允许窗口绘图:
void gtk_widget_set_app_paintable(
GtkWidget *widget,
gboolean app_paintable )
widget:控件指针
app_paintable:TRUE允许绘图,FALSE不允许
绘图注意事项(能不用绘图尽量不用,绘图效率较低):
1)尽量不要在绘图回调函数做太多的复杂数据处理,绘图的任务只是绘图,尽量不要做别的事情 (因为绘图随时有可能自动调用,导致效率很低)
2)绘图回调函数里一定不要调用gtk_widget_queue_draw() (因为会导致死循环,效率很低)
void fun()
{
gtk_widget_queue_draw() // error
}
绘图流程:
1)允许窗口能绘图(顺序随意)
2)连接曝光信号"expose-event"3)实现绘图回调函数(绘图是绘窗口里面的window成员,在GtkWidget这个结构体里能找到这个成员 )
以下例子为,通过绘图实现背景,按按钮窗口的笑脸会移动:
源码代码:
#include <cairo.h> // 绘图所需要的头文件
#include <gtk/gtk.h> int startx = ;
int w = ;
int h = ; // 绘图事件
gboolean on_expose_event (GtkWidget * widget, GdkEventExpose *event, gpointer data)
{
cairo_t *cr = gdk_cairo_create(widget->window); // 创建cairo环境,注意参数 // 画背景图
// 获取图片
GdkPixbuf *src_pixbuf = gdk_pixbuf_new_from_file("./image/back.jpg", NULL);
// 指定图片大小
GdkPixbuf* dst_pixbuf = gdk_pixbuf_scale_simple(src_pixbuf, w, h, GDK_INTERP_BILINEAR); // dst_pixbuf作为cr环境的画图原材料,(0, 0):画图的起点坐标
gdk_cairo_set_source_pixbuf(cr, dst_pixbuf, , );
cairo_paint(cr); // 绘图 // 释放资源
g_object_unref(dst_pixbuf);
g_object_unref(src_pixbuf); // 画笑脸
src_pixbuf = gdk_pixbuf_new_from_file("./image/face.png", NULL);
dst_pixbuf = gdk_pixbuf_scale_simple(src_pixbuf, , , GDK_INTERP_BILINEAR);
gdk_cairo_set_source_pixbuf(cr, dst_pixbuf, startx, (h/)*);
cairo_paint(cr);
g_object_unref(dst_pixbuf);
g_object_unref(src_pixbuf); /*
// 绘图与写字共存的测试
// 如果绘完图片后想继续写字或画线,
// 必须手动设置画笔颜色cairo_set_source_rgb()
// 否则,字体或线条会被图片覆盖。
cairo_set_source_rgb(cr, 0.627, 0, 0); // 设置字体颜色
cairo_set_font_size(cr, 40.0); // 设置字体大小
cairo_move_to(cr, 50.0, 130.0); // 写字的起点坐标
cairo_show_text(cr, "This is a test"); // 写字
*/ cairo_destroy(cr); // 回收所有Cairo环境所占用的内存资源 return FALSE; // 必须返回FALSE
} // 按钮按下回调函数
void deal_button_clicked(GtkWidget *widget, gpointer data)
{
startx += ;
if(startx >= w){
startx = ;
} gtk_widget_queue_draw( GTK_WIDGET(data) ); // 更新刷图区域,刷新整个窗口
} int main (int argc, char *argv[])
{
gtk_init (&argc, &argv); GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL); // 顶层窗口
g_signal_connect(window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); // 中央位置显示
gtk_widget_set_size_request(window, , ); // 窗口最小大小
gtk_window_set_resizable(GTK_WINDOW(window), FALSE); // 固定窗口的大小 GtkWidget *table = gtk_table_new(, , TRUE); // 表格布局容器
gtk_container_add(GTK_CONTAINER(window), table); // 容器加入窗口 // button
GtkWidget *button = gtk_button_new_with_label("click me"); // 按钮
g_signal_connect(button, "clicked", G_CALLBACK(deal_button_clicked), window);
gtk_table_attach_defaults(GTK_TABLE(table), button, , , , );// 把按钮加入布局 // 绘图事件信号与回调函数的连接
g_signal_connect(window, "expose-event", G_CALLBACK(on_expose_event), NULL); gtk_widget_set_app_paintable(window, TRUE); // 允许窗口可以绘图 gtk_widget_show_all(window); // 显示所有控件 gtk_main(); return ;
}
gtk界面设计的更多相关文章
- Java界面设计 Swing(1)
Java界面设计的用途 开发者可以通过Java SE开发丰富并且强大的具有图形界面的桌面应用程序.也可以设计一些提高效率的工具软件,帮助自己处理机械性工作. Java 的图形界面工具包,可以用于工具类 ...
- NanUI for Winform发布,让Winform界面设计拥有无限可能
如今,尽管WPF.UWP大行其道,大有把Winform打残干废的趋势.但是还是有那么一波顽固不化的老家伙们固守着Winform,其中就包括我. 好吧,既然都说Winform做得软件不如WPF界面美观效 ...
- Android开发1:基本UI界面设计——布局和组件
前言 啦啦啦~本学期要开始学习Android开发啦~ 博主在开始学习前是完完全全的小白,只有在平时完成老师要求的实验的过程中一步一步学习~从此篇博文起,博主将开始发布Android开发有关的博文,希望 ...
- iPhone / iPad UI界面设计与图标设计的尺寸设计规范+安卓+网页
①iPhone的设计尺寸 iPhone界面尺寸: 设备 分辨率 状态栏高度 导航栏高度 标签栏(工具栏)高度 iPhone6 plus设计版 1242 × 2208 60px 132px 146px ...
- 免费 PSD 素材:25个全新的界面设计资源
在这篇文章中,我们给大家收集了25套全新的 UI 设计素材.这些来自优秀设计师的 PSD 源文件素材让其它的设计师们在设计用户界面原型的时候能够非常便利. 网站用户界面,移动应用程序用户界面和对设计师 ...
- 26款能够吸引用户的 iPhone App 界面设计
在这个移动互联网告诉的时代,众多的移动应用程序涌现出来.谁能抓住用户的注意力,谁就有可能成功.在下面这些移动 App 界面设计中,你可以看到不同创意类型的视觉效果,让你获得灵感. 您可能感兴趣的相关文 ...
- android 界面设计基本知识Ⅲ
本章继续讲述在android界面设计中相关的知识点.介绍内容包括BroadcastReceiver(广播),Service(服务),Widget(小部件),WebView(网页加载控件). 1.Bro ...
- android 界面设计基本知识Ⅱ
上一章讲述了Android界面设计时,一些基本控件的使用,本章主要讲述自定义控件,Fragment和Headler线程机制. 1.自定义控件 (1)基本知识 dp.sp和dx px:像素点 ...
- android 界面设计基本知识
一个好的APP不仅有美观,好看的界面,更需要良好的性能和稳定性.作为一名开发人员,需要理解界面设计原则并写出优秀的界面设计代码. 本章主要讲述基本控件的使用,界面布局及一些常用的界面设计属性. 1.常 ...
随机推荐
- android 技术点记录
Android Service完全解析,关于服务你所需知道的一切(上) http://blog.csdn.net/guolin_blog/article/details/11952435 androi ...
- TCP和UDPsocket中SO_SNDBUF和SO_RCVBUF_转
1.Background Winsock kernel buffer To optimize performance at the application layer, Winsock copies ...
- 让jQuery的ajaxFileUpload插件支持onchange事件
ajaxFileUpload插件只能上传一次的BUG发现还不少人遇到,很不幸我也遇到的,使用后发现里面的坑还不少,在createUploadForm方法中有句 var newElement = jQu ...
- 30个开源电子商务系统(PHP)
osCommerce osCommerce是一款著名的PHP开源电子商务解决方案,提出“开箱即用”的强大功能,使网上商店安装非常方便快捷,并可以作为GNU通用公共授权的开源项目免费发布.osComme ...
- 【jquery】ajax 请求成功后新开窗口被拦截解决方法
问题: 前面开发项目时碰到一个问题,ajax 异步请求成功后需要新开窗口打开 url,使用的是 window.open() 方法,但是很可惜被浏览器给拦截了,怎么解决这个问题呢? 分析: 浏览器之所以 ...
- 测试word发表博客
哈哈哈 我测试一下 <ul class="clearfix"> <li> <div><img src="{IMG_PATH}qr ...
- const_cast的应用
对于const变量,我们不能修改它的值,这是这个限定符最直接的表现.但是我们就是想违背它的限定希望修改其内容怎么办呢?于是我们可以使用const_cast转换符是用来移除变量的const限定符.con ...
- QIODevice (Qt中所有 I/O devices 的基类,QFile,QBuffer,QTcpSocket等)
QIODevice是所有Qt I/O设备的基类,它提供了对支持块读写设备(例如QFile,QBuffer,QTcpSocket)的通用实现和抽象接口.QIODevice是一种抽象,不能被实例化,但是, ...
- wifi 通过omnipeek 查看 pmf是否生效
给android的wifi设备添加PMF支持时,抓取omnipeek分析. 从assoc req 中发现相关标志位没有使能,说明STA 没有使能PMF RSN Capabilities: %00000 ...
- Solr系列三:solr索引详解(Schema介绍、字段定义详解、Schema API 介绍)
一.Schema介绍 1. Schema 是什么? Schema:模式,是集合/内核中字段的定义,让solr知道集合/内核包含哪些字段.字段的数据类型.字段该索引存储. 2. Schema 的定义方式 ...