GTK+入门
Gtk图形界面的开发,也就是GUI开发,在这个阶段我们采用的是gtk+这个库,之所以采用这个库,是因为这个库给我们提供的接口是C语言的
1、什么是GUI
- GUI
- Graphics User Interface 图形用户接口
- 可以使操作更简单、更快捷、更人性化
- CUI
- Command line User Interface 命令行用户接口
2、空白窗口
#include <gtk/gtk.h>
int main(int argc, char *argv[])
{
/* gtk环境初始化 */
gtk_init(&argc, &argv);
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); /* 创建顶层窗口 */
gtk_window_set_title(GTK_WINDOW(window), "Window"); /* 设置窗口的标题 */
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); /* 设置窗口在显示器中的位置为居中 */
gtk_widget_set_size_request(window, 400, 300); /* 设置窗口的最小大小 */
gtk_window_set_resizable(GTK_WINDOW(window), FALSE); /* 固定窗口的大小 */
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); /* 给关闭页面绑定操作 */
gtk_widget_show_all(window); /* 展示所有控件 */
/* 主事件循环:用户在这时可以操作窗口 */
gtk_main();
return 0;
}
- 编译
gcc a.c -o a `pkg-config --cflags --libs gtk+-2.0`
# `为数字1左边的按键 --cflags:自动获取预处理参数,如宏定义、头文件的位置 --libs:自动获取链接参数
3、带按钮的窗口
#include <gtk/gtk.h>
int main(int argc, char *argv[])
{
/* gtk环境初始化 */
gtk_init(&argc, &argv);
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); /* 创建顶层窗口 */
gtk_window_set_title(GTK_WINDOW(window), "Window"); /* 设置窗口的标题 */
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); /* 设置窗口在显示器中的位置为居中 */
gtk_widget_set_size_request(window, 400, 300); /* 设置窗口的最小大小 */
gtk_window_set_resizable(GTK_WINDOW(window), FALSE); /* 固定窗口的大小 */
gtk_container_set_border_width(GTK_CONTAINER(window), 15); /* 设置窗口边框的宽度为15 */
GtkWidget *button = gtk_button_new_with_label("Hello World"); /* 创建按钮,文本信息为"Hello World" */
const char *str = gtk_button_get_label( GTK_BUTTON(button) ); /* 获得按钮的内容 */
printf("str = %s\n", str);
gtk_container_add(GTK_CONTAINER(window), button); /* 把按钮放入窗口 */
gtk_widget_show_all(window); /* 展示所有控件 */
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); /* 给关闭页面绑定操作 */
/* 主事件循环:用户在这时可以操作窗口 */
gtk_main();
return 0;
}
4、信号和回调函数
#include <gtk/gtk.h>
/* 按钮按下的处理函数:获取按钮的文本信息并在终端输出 */
void press_btn(GtkButton* button, gpointer user_data) /* gpointer 相当于 void* */
{
const char* str = gtk_button_get_label(GTK_BUTTON(button));
g_print("button_label_text=%s\n", str);
g_print("user_data:%s\n", (gchar*)user_data);
}
int main(int argc, char *argv[])
{
/* gtk环境初始化 */
gtk_init(&argc, &argv);
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); /* 创建顶层窗口 */
gtk_window_set_title(GTK_WINDOW(window), "Window"); /* 设置窗口的标题 */
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); /* 设置窗口在显示器中的位置为居中 */
gtk_widget_set_size_request(window, 400, 300); /* 设置窗口的最小大小 */
gtk_window_set_resizable(GTK_WINDOW(window), FALSE); /* 固定窗口的大小 */
gtk_container_set_border_width(GTK_CONTAINER(window), 15); /* 设置窗口边框的宽度为15 */
GtkWidget *button = gtk_button_new_with_label("Hello World"); /* 创建按钮,文本信息为"Hello World" */
const char *str = gtk_button_get_label( GTK_BUTTON(button) ); /* 获得按钮的内容 */
printf("str = %s\n", str);
gtk_container_add(GTK_CONTAINER(window), button); /* 把按钮放入窗口 */
gtk_widget_show_all(window); /* 展示所有控件 */
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); /* 给关闭页面绑定操作 */
g_signal_connect(button, "pressed", G_CALLBACK(press_btn), "Pressed Button");
/* 主事件循环:用户在这时可以操作窗口 */
gtk_main();
return 0;
}
g_signal_connect(gpointer instance,const gchar *detailed_signal,GCallback c_handler,gpointer data );instance:信号的发出者detailed_signal:要连接信号的名称c_handler:回调函数的名称,需要用G_CALLBACK()进行转换data:传递给回调函数的参数
5、布局
#include <gtk/gtk.h>
GtkWidget *entry; /* 因为在处理函数中会使用,所有定义为全局变量 */
GtkWidget *label;
/* 按钮按下的处理函数:获取按钮的文本信息并设置为标签和行编辑框文本 */
void press_btn(GtkButton* button, gpointer user_data)
{
const gchar* text = gtk_button_get_label(button);
g_print("button_text = %s; user_data = %s\n", text, (gchar*)user_data);
gtk_entry_set_text(GTK_ENTRY(entry), text);
gtk_label_set_text(GTK_LABEL(label), text);
}
int main(int argc, char* argv[])
{
/* gtk环境初始化 */
gtk_init(&argc, &argv);
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); /* 创建顶层窗口 */
gtk_window_set_title(GTK_WINDOW(window), "Window"); /* 设置窗口的标题 */
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); /* 设置窗口在显示器中的位置为居中 */
gtk_widget_set_size_request(window, 400, 300); /* 设置窗口的最小大小 */
gtk_window_set_resizable(GTK_WINDOW(window), FALSE); /* 固定窗口的大小 */
gtk_container_set_border_width(GTK_CONTAINER(window), 15); /* 设置窗口边框的宽度为15 */
GtkWidget *fixed = gtk_fixed_new(); /* 创建固定布局 */
gtk_container_add(GTK_CONTAINER(window), fixed); /* 布局加到窗口里 */
GtkWidget *button1 = gtk_button_new_with_label("确定"); /* 创建按钮 */
gtk_fixed_put(GTK_FIXED(fixed), button1, 50, 50); /* 按钮放到布局里 */
GtkWidget *button2 = gtk_button_new_with_label("取消");
gtk_fixed_put(GTK_FIXED(fixed), button2, 50 * 2, 50 * 2);
GtkWidget *button3 = gtk_button_new_with_label("返回");
gtk_fixed_put(GTK_FIXED(fixed), button3, 50 * 3, 50 * 3);
entry = gtk_entry_new(); /* 创建行编辑框 */
gtk_widget_set_size_request(entry, 200, 40); /* 设置行编辑框大小 */
gtk_entry_set_max_length(GTK_ENTRY(entry), 100); /* 设置行编辑框显示最大字符长度 */
gtk_entry_set_text(GTK_ENTRY(entry), "hello world"); /* 设置行编辑框默认值 */
gtk_fixed_put(GTK_FIXED(fixed), entry, 50, 200);
label = gtk_label_new("hello world"); /* 创建标签 */
gtk_widget_set_size_request(label, 200, 40);
gtk_fixed_put(GTK_FIXED(fixed), label, 50, 10);
gtk_widget_show_all(window); /* 展示所有控件 */
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); /* 给关闭页面绑定操作 */
g_signal_connect(button1, "pressed", G_CALLBACK(press_btn), "Pressed Button");
g_signal_connect(button2, "pressed", G_CALLBACK(press_btn), "Pressed Button");
g_signal_connect(button3, "pressed", G_CALLBACK(press_btn), "Pressed Button");
/* 主事件循环:用户在这时可以操作窗口 */
gtk_main();
return 0;
}
Example:计算器
#include <gtk/gtk.h>
GtkWidget *entry;
void press_btn(GtkButton* button, gpointer user_data)
{
const gchar* text = gtk_button_get_label(button);
g_print("button_text = %s; user_data = %s\n", text, (gchar*)user_data);
gtk_entry_set_text(GTK_ENTRY(entry), text);
}
int main(int argc, char* argv[])
{
/* gtk环境初始化 */
gtk_init(&argc, &argv);
/* 窗口设置 */
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); /* 顶层窗口 */
gtk_window_set_title(GTK_WINDOW(window), "计算器"); /* 窗口标题 */
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);/* 窗口居中 */
gtk_widget_set_size_request(window, 400, 300); /* 设置窗口大小 */
gtk_window_set_resizable(GTK_WINDOW(window), FALSE); /* 固定窗口大小 */
gtk_container_set_border_width(GTK_CONTAINER(window), 10); /* 设置窗口边框宽度 */
/* 网格布局 */
GtkWidget *table = gtk_table_new(6, 4, TRUE); /* 5行4列控件均衡排放 */
gtk_container_add(GTK_CONTAINER(window), table); /* 布局放到窗口里 */
/* 控件:按钮、行编辑框 */
GtkWidget *button0 = gtk_button_new_with_label("0"); /* 0 */
gtk_table_attach_defaults(GTK_TABLE(table), button0, 0, 1, 5, 6);
GtkWidget *button1 = gtk_button_new_with_label("1"); /* 1 */
gtk_table_attach_defaults(GTK_TABLE(table), button1, 0, 1, 4, 5);
GtkWidget *button2 = gtk_button_new_with_label("2"); /* 2 */
gtk_table_attach_defaults(GTK_TABLE(table), button2, 1, 2, 4, 5);
GtkWidget *button3 = gtk_button_new_with_label("3"); /* 3 */
gtk_table_attach_defaults(GTK_TABLE(table), button3, 2, 3, 4, 5);
GtkWidget *button4 = gtk_button_new_with_label("4"); /* 4 */
gtk_table_attach_defaults(GTK_TABLE(table), button4, 0, 1, 3, 4);
GtkWidget *button5 = gtk_button_new_with_label("5"); /* 5 */
gtk_table_attach_defaults(GTK_TABLE(table), button5, 1, 2, 3, 4);
GtkWidget *button6 = gtk_button_new_with_label("6"); /* 6 */
gtk_table_attach_defaults(GTK_TABLE(table), button6, 2, 3, 3, 4);
GtkWidget *button7 = gtk_button_new_with_label("7"); /* 7 */
gtk_table_attach_defaults(GTK_TABLE(table), button7, 0, 1, 2, 3);
GtkWidget *button8 = gtk_button_new_with_label("8"); /* 8 */
gtk_table_attach_defaults(GTK_TABLE(table), button8, 1, 2, 2, 3);
GtkWidget *button9 = gtk_button_new_with_label("9"); /* 9 */
gtk_table_attach_defaults(GTK_TABLE(table), button9, 2, 3, 2, 3);
GtkWidget *button10 = gtk_button_new_with_label("."); /* . */
gtk_table_attach_defaults(GTK_TABLE(table), button10, 1, 2, 5, 6);
GtkWidget *button11 = gtk_button_new_with_label("="); /* = */
gtk_table_attach_defaults(GTK_TABLE(table), button11, 2, 3, 5, 6);
GtkWidget *button12 = gtk_button_new_with_label("+"); /* + */
gtk_table_attach_defaults(GTK_TABLE(table), button12, 3, 4, 5, 6);
GtkWidget *button13 = gtk_button_new_with_label("-"); /* - */
gtk_table_attach_defaults(GTK_TABLE(table), button13, 3, 4, 4, 5);
GtkWidget *button14 = gtk_button_new_with_label("*"); /* * */
gtk_table_attach_defaults(GTK_TABLE(table), button14, 3, 4, 3, 4);
GtkWidget *button15 = gtk_button_new_with_label("/"); /* / */
gtk_table_attach_defaults(GTK_TABLE(table), button15, 3, 4, 2, 3);
GtkWidget *button16 = gtk_button_new_with_label("Backspace"); /* Backspace */
gtk_table_attach_defaults(GTK_TABLE(table), button16, 0, 2, 1, 2);
GtkWidget *button17 = gtk_button_new_with_label("C"); /* Clear */
gtk_table_attach_defaults(GTK_TABLE(table), button17, 2, 4, 1, 2);
entry = gtk_entry_new(); /* 创建行编辑框 */
gtk_entry_set_max_length(GTK_ENTRY(entry), 100); /* 设置最大显示长度 */
gtk_entry_set_text(GTK_ENTRY(entry), ""); /* 设置内容 */
gtk_table_attach_defaults(GTK_TABLE(table), entry, 0, 4, 0, 1);
gtk_widget_show_all(window); /* 展示所有控件 */
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); /* 绑定关闭操作 */
g_signal_connect(button0, "pressed", G_CALLBACK(press_btn), "0");
g_signal_connect(button1, "pressed", G_CALLBACK(press_btn), "1");
g_signal_connect(button2, "pressed", G_CALLBACK(press_btn), "2");
g_signal_connect(button3, "pressed", G_CALLBACK(press_btn), "3");
g_signal_connect(button4, "pressed", G_CALLBACK(press_btn), "4");
g_signal_connect(button5, "pressed", G_CALLBACK(press_btn), "5");
g_signal_connect(button6, "pressed", G_CALLBACK(press_btn), "6");
g_signal_connect(button7, "pressed", G_CALLBACK(press_btn), "7");
g_signal_connect(button8, "pressed", G_CALLBACK(press_btn), "8");
g_signal_connect(button9, "pressed", G_CALLBACK(press_btn), "9");
g_signal_connect(button10, "pressed", G_CALLBACK(press_btn), ".");
g_signal_connect(button11, "pressed", G_CALLBACK(press_btn), "=");
g_signal_connect(button12, "pressed", G_CALLBACK(press_btn), "+");
g_signal_connect(button13, "pressed", G_CALLBACK(press_btn), "-");
g_signal_connect(button14, "pressed", G_CALLBACK(press_btn), "*");
g_signal_connect(button15, "pressed", G_CALLBACK(press_btn), "/");
g_signal_connect(button16, "pressed", G_CALLBACK(press_btn), "Backspace");
g_signal_connect(button17, "pressed", G_CALLBACK(press_btn), "C");
/* 主事件循环:用户在这时可以操作窗口 */
gtk_main();
return 0;
}
Example:登录器(不完全体)
#include <gtk/gtk.h>
#include <string.h>
GtkWidget *label_user_input;
GtkWidget *entry_username, *entry_password, *entry_test;
/*
登录功能
1.点击登录按钮,让登录按钮触发一个登录事件
2.先将登录按钮绑定一个信号连接函数
3.自定义函数,是回调函数,有固定格式
功能分析:
1.系统生成验证码
2.接收用户输入的验证码
3.两者比较
- 一致:显示验证码正确
- 不一致:显示验证码不正确
*/
void btn_login(GtkButton *button, gpointer user_data)
{
const char *test = gtk_label_get_text(GTK_LABEL(label_user_input));
const char *input = gtk_entry_get_text(GTK_ENTRY(entry_test));
if(0 == strcmp(input, test))
{
gtk_label_set_text(GTK_LABEL(label_user_input), "验证码正确");
gtk_label_set_markup(GTK_LABEL(label_user_input), "<span foreground='#686fed' font_desc='10'>验证码正确</span>");
}
else
{
gtk_label_set_text(GTK_LABEL(label_user_input), "验证码错误");
gtk_label_set_markup(GTK_LABEL(label_user_input), "<span foreground='red' font_desc='10'>验证码错误</span>");
}
}
void btn_refresh(GtkButton *button, gpointer user_data)
{
gtk_entry_set_text(GTK_ENTRY(entry_username), "");
gtk_entry_set_text(GTK_ENTRY(entry_password), "");
gtk_entry_set_text(GTK_ENTRY(entry_test), "");
int i;
char a[4] = ""; /* 存放系统随机生成验证码 */
srand(time(NULL)); /* 生成随机因子 */
for(i = 0; i < 4; ++i)
{
a[i] = rand() % 10 + '0';
}
gtk_label_set_text(GTK_LABEL(label_user_input), a);
}
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, 128);
// 通过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环境初始化 */
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, 400, 300);
chang_background(window, 400, 300, "./5.jpg"); /* 通过自定义函数添加背景图片 */
gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_container_set_border_width(GTK_CONTAINER(window), 15);
/* 设置布局 */
GtkWidget *table = gtk_table_new(5, 5, TRUE); /* 5行7列均衡排列 */
gtk_container_add(GTK_CONTAINER(window), table);
GtkWidget *hbox = gtk_hbox_new(TRUE, 0); /* 水平均衡排列,控件无间隔 */
gtk_table_attach_defaults(GTK_TABLE(table), hbox, 0, 5, 4, 5);
/* 设置控件 */
// 标签 + 行编辑框
GtkWidget *label_title = gtk_label_new("王者荣耀");
/* 通过gtk_label_set_markup函数使用HTML5语言修改标签文本大小及颜色 */
gtk_label_set_markup(GTK_LABEL(label_title), "<span foreground='black' font_desc='24'>王者荣耀</span>");
gtk_table_attach_defaults(GTK_TABLE(table), label_title, 1, 4, 0, 1);
GtkWidget *label_username = gtk_label_new("账号:");
gtk_label_set_markup(GTK_LABEL(label_username), "<span foreground='black' font_desc='14'>账号:</span>");
gtk_table_attach_defaults(GTK_TABLE(table), label_username, 0, 1, 1, 2);
entry_username = gtk_entry_new();
gtk_table_attach_defaults(GTK_TABLE(table), entry_username, 1, 5, 1, 2);
GtkWidget *label_password = gtk_label_new("密码:");
gtk_label_set_markup(GTK_LABEL(label_password), "<span foreground='black' font_desc='14'>密码:</span>");
gtk_table_attach_defaults(GTK_TABLE(table), label_password, 0, 1, 2, 3);
entry_password = gtk_entry_new();
gtk_table_attach_defaults(GTK_TABLE(table), entry_password, 1, 5, 2, 3);
GtkWidget *label_test = gtk_label_new("验证码:");
gtk_label_set_markup(GTK_LABEL(label_test), "<span foreground='black' font_desc='14'>验证码:</span>");
gtk_table_attach_defaults(GTK_TABLE(table), label_test, 0, 1, 3, 4);
entry_test = gtk_entry_new();
gtk_table_attach_defaults(GTK_TABLE(table), entry_test, 1, 4, 3, 4);
// 系统验证码
label_user_input = gtk_label_new("");
gtk_table_attach_defaults(GTK_TABLE(table), label_user_input, 4, 5, 3, 4);
int i;
char a[4] = "";
srand(time(NULL));
for(i = 0; i < 4; ++i)
{
a[i] = rand() % 10 + '0';
}
gtk_label_set_text(GTK_LABEL(label_user_input), a);
// 按钮
GtkWidget *button_login = gtk_button_new_with_label("登录");
gtk_button_set_relief(GTK_BUTTON(button_login), GTK_RELIEF_NONE); /* 设置按钮为透明 */
gtk_container_add(GTK_CONTAINER(hbox), button_login);
GtkWidget *button_refresh = gtk_button_new_with_label("刷新");
gtk_button_set_relief(GTK_BUTTON(button_refresh), GTK_RELIEF_NONE);
gtk_container_add(GTK_CONTAINER(hbox), button_refresh);
GtkWidget *button_register = gtk_button_new_with_label("注册");
gtk_button_set_relief(GTK_BUTTON(button_register), GTK_RELIEF_NONE);
gtk_container_add(GTK_CONTAINER(hbox), button_register);
gtk_widget_show_all(window); /* 展示所有控件 */
/* 信号连接 */
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(button_login, "pressed", G_CALLBACK(btn_login), NULL);
g_signal_connect(button_refresh, "pressed", G_CALLBACK(btn_refresh), NULL);
/* 主事件循环:用户在这时可以操作窗口 */
gtk_main();
return 0;
}
这篇文章介绍了GTK+库在GUI开发中的应用,从基本的窗口创建到添加按钮,再到信号和回调函数的使用,以及布局管理,逐步展示了如何使用C语言构建图形界面程序。示例包括创建带按钮的窗口、响应按钮点击和实现简单的布局设计。
2477

被折叠的 条评论
为什么被折叠?



