GTK-2.0入门

这篇文章介绍了GTK+库在GUI开发中的应用,从基本的窗口创建到添加按钮,再到信号和回调函数的使用,以及布局管理,逐步展示了如何使用C语言构建图形界面程序。示例包括创建带按钮的窗口、响应按钮点击和实现简单的布局设计。

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;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值