Gtk常用控件

按钮(GtkButton)

// 带图标按钮的创建
// image: 通过 gtk_image_new_from_file()来创建, 参数为图片的路径
void gtk_button_set_image(GtkButton *button, GtkWidget *image);
// 设置按钮透明背景色
// newstyle: GTK_RELIEF_NONE 为透明
void gtk_button_set_relief(GtkButton *button, GtkReliefStyle newstyle);

栗子 : button.c

/* * @由于个人水平有限, 难免有些错误, 还请指点: * @Author: cpu_code * @Date: 2020-08-05 11:20:39 * @LastEditTime: 2020-08-05 11:35:04 * @FilePath: \gtk\button_image\button_image.c * @Gitee: [https://gitee.com/cpu_code](https://gitee.com/cpu_code) * @Github: [https://github.com/CPU-Code](https://github.com/CPU-Code) * @CSDN: [https://blog.csdn.net/qq_44226094](https://blog.csdn.net/qq_44226094) * @Gitbook: [https://923992029.gitbook.io/cpucode/](https://923992029.gitbook.io/cpucode/) */

//头文件
#include <gtk/gtk.h>

// 回调函数
void callback(GtkButton *button, gpointer data)
{
    //获得按钮的文本内容
    const char *str = gtk_button_get_label(button);

    printf("str = %s\n", str);
    // 图像控件
    GtkWidget *image = gtk_image_new_from_file("1.png");
    gtk_button_set_image(GTK_BUTTON(button), image);
}

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), "cpucode button");
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
    // 设置窗口边框的宽度
    gtk_container_set_border_width(GTK_CONTAINER(window), 10);       

    // 窗口居中
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); 

    GtkWidget *hbox = gtk_hbox_new(TRUE, 10); 		// 水平布局容器
	gtk_container_add(GTK_CONTAINER(window), hbox); // 把横向盒状容器放入窗口

    // 普通按钮
	GtkWidget *normal_button = gtk_button_new_with_label("normal button");
    
    gtk_button_set_label(GTK_BUTTON(normal_button), "change");	// 设置按钮的文本内容
	g_signal_connect(normal_button, "pressed", G_CALLBACK(callback), NULL);
	gtk_container_add(GTK_CONTAINER(hbox), normal_button);     // 把按钮放入横向容器里

    // 带图标按钮
	GtkWidget *button = gtk_button_new(); // 先创建空按钮
	GtkWidget *image = gtk_image_new_from_file("1.png"); // 图像控件

    gtk_button_set_image(GTK_BUTTON(button), image);
	gtk_container_add(GTK_CONTAINER(hbox), button);     // 把按钮放入横向容器里
	gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);	// 按钮背景色透明


	// 按钮使能设置,默认为使能TRUE,非使能FALSE
	//gtk_widget_set_sensitive(button, FALSE);

	gtk_widget_show_all(window);	// 显示窗口控件

	gtk_main(); 	// 主事件循环

    return 0; 
}

图片 :

Makefile

CC = gcc  
MAINC = button_image.c
EXEC = button_image

CFLAGS = `pkg-config --cflags --libs gtk+-2.0`

main:  
	$(CC)  $(MAINC)  -o $(EXEC) $(CFLAGS)
clean:
	rm $(EXEC) -rf

图片资源对象(GdkPixbuf)

// 图片资源对象的创建
// filename: 图片路径
// error: 储存错误的指针
GdkPixbuf *gdk_pixbuf_new_from_file(const gchar *filename, GError **error);
// 设置图片的大小
// interp_type: 是一个枚举变量, 标志图片的加载速度和质量, 常用 GDK_INTERP_BILINEAR
GdkPixbuf *gdk_pixbuf_scale_simple(const GdkPixbuf *src, int dest_width, int dest_height, GdkInterpType interp_type);
// 释放资源
void g_object_unref(GtkObject *object);

图片控件(GtkImage)

// 通过图片资源对象创建图片控件
GtkWidget *gtk_image_new_from_pixbuf(GdkPixbuf *pixbuf );
// 图片控件重新设置一张图片(pixbuf)
void gtk_image_set_froma_pixbuf(GtkImage *image, GdkPixbuf *pixbuf );
//清除控件里的图像数据
void gtk_image_clear(GtkImage *image);

栗子 : image.c

#include <gtk/gtk.h>

typedef struct _Window
{
	GtkWidget *main_window;
	GtkWidget *table;
	GtkWidget *image;
	GtkWidget *button_previous;
	GtkWidget *button_next;
}WINDOW;

// 给创建好的image重新设计一张图片
void load_image(GtkWidget *image, const char *file_path, const int w, const int h )
{
    gtk_image_clear( GTK_IMAGE(image) );        // 清除图像
	GdkPixbuf *src_pixbuf = gdk_pixbuf_new_from_file(file_path, NULL);	// 创建图片资源
    GdkPixbuf *dest_pixbuf = gdk_pixbuf_scale_simple(src_pixbuf, w, h, GDK_INTERP_BILINEAR); // 指定大小

    gtk_image_set_from_pixbuf(GTK_IMAGE(image), dest_pixbuf); // 图片控件重新设置一张图片(pixbuf)
    g_object_unref(src_pixbuf);		// 释放资源
	g_object_unref(dest_pixbuf);	// 释放资源
}

// 根据图片路径创建一个新按钮,同时指定图片大小
GtkWidget *create_button_from_file(const char *file_path, const int w, const int h)
{
    GtkWidget *temp_image = gtk_image_new_from_pixbuf(NULL);
    load_image(temp_image, file_path, w, h);

    GtkWidget *button = gtk_button_new(); 					// 先创建空按钮

    gtk_button_set_image(GTK_BUTTON(button), temp_image);	// 给按钮设置图标
	gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);	// 按钮背景色透明

	return button;
}

// 按钮的回调函数
void deal_switch_image(GtkWidget *button, gpointer data)
{
    WINDOW *p_temp = (WINDOW *)data;

    if(button == p_temp->button_previous)
    {		// 上一张
        printf("p_temp->button_previous\n");
    }
    else if(button == p_temp->button_next )
    {	// 下一张
        printf("p_temp->button_next\n");
    }
}

void window_demo(gpointer data)
{
    WINDOW *p_temp = (WINDOW *)data;

    // 主窗口
	p_temp->main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);		 	// 创建主窗口

    gtk_window_set_title(GTK_WINDOW(p_temp->main_window), "cpucode image");	 	// 设置窗口标题
    gtk_window_set_position(GTK_WINDOW(p_temp->main_window), GTK_WIN_POS_CENTER); // 设置窗口在显示器中的位置为居中
    gtk_widget_set_size_request(p_temp->main_window, 800, 480);		 	// 设置窗口的最小大小
    gtk_window_set_resizable(GTK_WINDOW(p_temp->main_window), FALSE); 	// 固定窗口的大小
	g_signal_connect(p_temp->main_window, "destroy", G_CALLBACK(gtk_main_quit), NULL);

    // 表格布局
	p_temp->table = gtk_table_new(7, 7, TRUE);	 					      // 表格布局容器
	gtk_container_add(GTK_CONTAINER(p_temp->main_window), p_temp->table); // 容器加入窗口

    // 图片控件
	p_temp->image = gtk_image_new_from_pixbuf(NULL);		// 创建图片控件
	load_image(p_temp->image, "./image/1.jpg", 500, 450);
	gtk_table_attach_defaults(GTK_TABLE(p_temp->table), p_temp->image, 1, 6, 1, 6);	// 把图片控件加入布局

    // 按钮
	p_temp->button_previous = create_button_from_file("./image/previous.bmp", 80, 80);
	gtk_table_attach_defaults(GTK_TABLE(p_temp->table), p_temp->button_previous, 1, 2, 6, 7);
	g_signal_connect(p_temp->button_previous, "clicked", G_CALLBACK(deal_switch_image), p_temp);

    p_temp->button_next = create_button_from_file("./image/next.bmp", 80, 80);
	gtk_table_attach_defaults(GTK_TABLE(p_temp->table), p_temp->button_next, 5, 6, 6, 7);
	g_signal_connect(p_temp->button_next, "clicked", G_CALLBACK(deal_switch_image), p_temp);

    gtk_widget_show_all(p_temp->main_window);
}

int main(int argc, char *argv[])
{
	gtk_init(&argc, &argv);		// 初始化
	
	WINDOW window;
	window_demo(&window);

	gtk_main();			// 主事件循环

	return 0;
}

Makefile

CC = gcc  
MAINC = image.c
EXEC = image_

CFLAGS = `pkg-config --cflags --libs gtk+-2.0`

main:  
	$(CC)  $(MAINC)  -o $(EXEC) $(CFLAGS)
clean:
	rm $(EXEC) -rf

进度条(GtkProgressBar)

// 进度条的创建
GtkWidget *gtk_progress_bar_new(void);  
// 设置进度条显示的百分比
// fraction: 0.0 到 1.0
void gtk_progress_bar_set_fraction(GtkProgressBar *pbar, gdouble fraction);
//设置滑槽上的文本显示
void gtk_progress_bar_set_text(GtkProgressBar *pbar, gchar *text);
/* * 设置进度条的移动方向 * GTK_PROGRESS_LEFT_TO_RIGHT : 从左向右 * GTK_PROGRESS_RIGHT_TO_LEFT : 从右向左 * GTK_PROGRESS_BOTTOM_TO_TOP : 从下向上 * GTK_PROGRESS_TOP_TO_BOTTOM : 从上向下 */
void gtk_progress_bar_set_orientation(GtkProgressBar *pbar, GtkProgressBarOrientation orientation);

栗子 : progress_bar.c

#include <gtk/gtk.h>
#include <string.h>

// 回调函数,切换进度条的移动方向 
void toggle_orientation(GtkWidget *widget, gpointer data) 
{ 
	// gtk_progress_bar_get_orientation: 获得进度条当前移动的方向
	switch( gtk_progress_bar_get_orientation( GTK_PROGRESS_BAR(data) ) )
    { 
        case GTK_PROGRESS_LEFT_TO_RIGHT: 
            gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(data), GTK_PROGRESS_RIGHT_TO_LEFT); 
            break; 

        case GTK_PROGRESS_RIGHT_TO_LEFT: 
            gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(data), GTK_PROGRESS_LEFT_TO_RIGHT); 
            break; 
            
        default: // 什么也不做 
            break;
	} 
} 

// 更新进度条,这样就能够看到进度条的移动
void callback(GtkWidget *widget, gpointer data)
{
	// 在原来值基础上增加 0.05
	gdouble new_val = gtk_progress_bar_get_fraction( GTK_PROGRESS_BAR(data) ) + 0.05; 
	   
	if(new_val > 1.0)
	{	
		// 越界处理
		new_val = 0.0; 
	}
	   
	// 设置进度条的新值 
	gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(data), new_val); 
}

int main(int argc, char *argv[])
{
    gtk_init(&argc, &argv);		// 初始化
    // 创建主窗口
    GtkWidget *window = gkt_window_new(GTK_WINDOW_TOPLEVEL);

    gtk_window_set_title(GTK_WINDOW(window), "cpucode GtkProgressBar");		// 设置窗口标题
    gtk_container_set_border_width(GTK_CONTAINER(window), 10);		// 设置边框宽度
    // 设置窗口在显示器中的位置为居中
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    // 设置窗口的最小大小
	gtk_widget_set_size_request(window, 300, 200);
    // 窗口关联 destroy 信号 到 gtk_main_quit
	g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);

    GtkWidget *vbox = gtk_vbox_new(FALSE, 5);		 // 垂直布局容器
    gtk_container_add(GTK_CONTAINER(window), vbox);  // 容器加入窗口

    // 创建一个进度条
	GtkWidget *progress = gtk_progress_bar_new();
    gtk_container_add(GTK_CONTAINER(vbox), progress);  // 加入垂直布局容器

    // 设置进度条显示的百分比:50%
	gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), 0.5 );
    // 设置在进度条的滑槽上的文本显示 
	gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress), "some text");

    // 添加一个按钮,切换移动方向 
    GtkWidget *button_orientation = gtk_button_new_with_label("Right to Left"); 
    g_signal_connect(button_orientation, "clicked", G_CALLBACK(toggle_orientation), progress); // connect
    gtk_container_add(GTK_CONTAINER(vbox), button_orientation);  // 加入垂直布局容器

    // 增加进度条进度按钮
	GtkWidget *button = gtk_button_new_with_label("add");
	g_signal_connect(button, "clicked", G_CALLBACK(callback), progress); // connect
	gtk_container_add(GTK_CONTAINER(vbox), button);  // 加入垂直布局容器
    
    gtk_widget_show_all(window);

    // 主事件循环
    gtk_main();

    return 0;
}

Makefile

CC = gcc  
MAINC = progress_bar.c
EXEC = progress_bar

CFLAGS = `pkg-config --cflags --libs gtk+-2.0`

main:  
	$(CC)  $(MAINC)  -o $(EXEC) $(CFLAGS)
clean:
	rm $(EXEC) -rf

滚动窗口(GtkScrolledWindow)

//滚动窗口的创建
// hadjustment : 水平方向的调整对象
// vadjustment : 垂直方向的调整对象。 它们一般都设置为 NULL。
GtkWidget *gtk_scrolled_window_new(GtkAdjustment *hadjustment, GtkAdjustment *vadjustment );
//滚动窗口添加控件
void gtk_scrolled_window_add_with_viewport(GtkScrolledWindow *scrolled_window, GtkWidget *child );
// 设置滚动条出现的方式(水平或垂直方向)
// GTK_POLICY_AUTOMATIC: 滚动条根据需要自动出现
// GTK_POLICY_ALWAYS: 滚动条总是出现
// GTK_POLICY_NEVER: 不需要滚动条
void gtk_scrolled_window_set_policy(GtkScrolledWindow *scrolled_window, 
                        GtkPolicyType hscrollbar_policy, 
                        GtkPolicyType vscrollbar_policy );

栗子 : scrolled_window.c 滚动窗口

#include <gtk/gtk.h> 

// 回调函数
void destroy( GtkWidget *widget, gpointer data ) 
{ 
    gtk_main_quit(); 
}

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), "cpucode ScrolledWindow");
	// 设置窗口在显示器中的位置为居中
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    g_signal_connect(window, "destroy", G_CALLBACK(destroy), NULL); 
    gtk_widget_set_size_request(window, 300, 200); // 设置窗口的最小大小

    /* 创建一个新的滚动窗口。 * 第一个参数是水平方向的调整对象 * 第二个参数是垂直方向的调整对象。 * 它们总是设置为NULL。 */
    GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL); 
    gtk_container_set_border_width(GTK_CONTAINER(scrolled_window), 10); 
	gtk_container_add(GTK_CONTAINER(window), scrolled_window); // 滚动窗口放入窗口

    /* * 滚动条的出现方式可以是 GTK_POLICY_AUTOMATIC 或 GTK_POLICY_ALWAYS。 * GTK_POLICY_AUTOMATIC:将自动决定是否需要出现滚动条 * 第一个是设置水平滚动条 * 第二个是垂直滚动条 */ 
    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), 
                                   GTK_POLICY_AUTOMATIC, 
                                   GTK_POLICY_AUTOMATIC); 

    // 标签
	GtkWidget *label = gtk_label_new("cpucode"\
	   "cpucode cpucode"\
       "cpucode cpucode cpucode"\
       "cpucode cpucode cpucode cpucode "\
       "cpucode cpucode cpucode cpucode cpucode cpucode cpucode cpucode"); 
    gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); 	// label 自动换行

    // 将标签组装到滚动窗口中 
    gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), label); 

    gtk_widget_show_all(window); 
     
    gtk_main(); 
     
    return 0;
}

Makefile

CC = gcc  
MAINC = scrolled_window.c
EXEC = scrolled_window

CFLAGS = `pkg-config --cflags --libs gtk+-2.0`

main:  
	$(CC)  $(MAINC)  -o $(EXEC) $(CFLAGS)
clean:
	rm $(EXEC) -rf

分栏列表控件(GtkCList)

// 列表的创建
// columns: 列数
// titles: 标题, 指针数目应该与列数相等
GtkWidget *gtk_clist_new_with_titles(gint columns, gchar *titles[]);
// 设置某一列的宽度
void gtk_clist_set_column_width(GtkCList *clist, gint column, gint width);
//设置某列内容显示的对齐方式
// GTK_JUSTIFY_LEFT: 左对齐
// GTK_JUSTIFY_RIGHT: 右对齐
// GTK_JUSTIFY_CENTER: 居中对齐
// GTK_JUSTIFY_FILL: 填充
void gtk_clist_set_column_justification(GtkCList *clist, gint column, GtkJustification justification );
// 向列表中添加行
gint gtk_clist_append( GtkCList *clist, gchar *text[] );
// 删除列表中所有的行
void gtk_clist_clear(GtkCList *clist);
//获取某一行某一列的内容
gint gtk_clist_get_text(GtkCList *clist, gint row, gint column, gchar **text );
//常用信号, 选中某一行触发
select-row

栗子 : list.c 分栏列表

#include <gtk/gtk.h>

// 用户点击"Add List"按钮时的回调函数
void button_add_clicked( GtkWidget *widget, gpointer data )
{
    char *a[2] = {"Mike",  "3 Oz"};
    gtk_clist_append( (GtkCList *)data, a );

    char *b[2] = { "Water",   "6 l" };
	gtk_clist_append( (GtkCList *)data, b );
}

//用户点击"Clear List" 按钮时的回调函数
void button_clear_clicked( GtkWidget *widget, gpointer data )
{
	/* 用gtk_clist_clear函数清除列表。比用 * gtk_clist_remove函数逐行清除要快 */
	gtk_clist_clear( (GtkCList *)data );
}

// 用户选中某一行时的回调函数
void selection_made( GtkWidget *clist, gint row, 
                     gint column, GdkEventButton *event, 
                     gpointer data )
{
	gtk_widget_queue_draw(clist);	// 人为更新列表,开发板有效
	
	gchar *text;
	
	/* 取得存储在被选中的行和列的单元格上的文本 * 当鼠标点击时,我们用text参数接收一个指针 */
	gtk_clist_get_text(GTK_CLIST(clist), row, column, &text);
	//打印一些关于选中了哪一行的信息
	g_print("第%d行,第%d列的内容为%s\n", row, column, text);
}

int main( int argc, gchar *argv[] )
{
	gtk_init(&argc, &argv);					// 初始化

    // 主窗口
	GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);	// 创建窗口
    gtk_widget_set_size_request(GTK_WIDGET(window), 300, 300);	// 设置最小大小
	gtk_window_set_title(GTK_WINDOW(window), "cpucode GtkCList ");	// 设置标题
	gtk_window_set_resizable(GTK_WINDOW(window), FALSE); 			// 固定窗口大小
	g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit),  NULL);

    // 表格布局容器
	GtkWidget *table = gtk_table_new(5, 2, TRUE);
	gtk_container_add(GTK_CONTAINER(window), table);

    /* 创建一个滚动窗口构件,将GtkCList组装到里面。 * 这样使得内容超出列表时,可以用滚动条浏览 * 第一个参数是水平方向的调整对象, * 第二个参数是垂直方向的调整对象。 * 它们总是设置为NULL。 */
	GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL);
	gtk_table_attach_defaults(GTK_TABLE(table), scrolled_window, 0, 2, 0, 4);// 把按钮加入布局

    // GTK_POLICY_AUTOMATIC:滚动条根据需要自动出现时
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
					               GTK_POLICY_AUTOMATIC, 
                                   GTK_POLICY_AUTOMATIC);

    gchar *titles[2] = { "Ingredients", "Amount" };
	// 创建GtkCList构件。本例中,我们使用了两列
	GtkWidget *clist = gtk_clist_new_with_titles(2, titles);
	// 将GtkCList构件添加到滚动窗口构件中
	gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled_window), clist);

    /* 设置某列内容显示的对齐方式 * GTK_JUSTIFY_LEFT : 列中的文本左对齐。 * GTK_JUSTIFY_RIGHT : 列中的文本右对齐。 * GTK_JUSTIFY_CENTER :列中的文本居中对齐。 * GTK_JUSTIFY_FILL : 文本使用列中所有可用的空间 */
	gtk_clist_set_column_justification(GTK_CLIST(clist), 1, GTK_JUSTIFY_CENTER);
	 
	/* 很重要的一点,我们设置列宽,让文本能容纳在列中。 * 注意,列编号是从0开始的, 本例中是0和1 */
	gtk_clist_set_column_width(GTK_CLIST(clist), 0, 150);
	
	// 选择某一行时触发selection_made回调函数
	g_signal_connect(clist, "select-row", G_CALLBACK(selection_made), NULL);

    // 按钮的创建,并放进布局容器里
	GtkWidget *button_add = gtk_button_new_with_label("Add List");
	GtkWidget *button_clear = gtk_button_new_with_label("Clear List");
    
	gtk_table_attach_defaults(GTK_TABLE(table), button_add, 0, 1, 4, 5);// 把按钮加入布局
	gtk_table_attach_defaults(GTK_TABLE(table), button_clear, 1, 2, 4, 5);// 把按钮加入布局

    // 为按钮的点击设置回调函数
	g_signal_connect(button_add, "clicked", G_CALLBACK(button_add_clicked), (gpointer)clist);
	g_signal_connect(button_clear, "clicked", G_CALLBACK(button_clear_clicked), (gpointer)clist);

	gtk_clist_set_row_style(GTK_CLIST(clist), 2, NULL);

    /* 界面已经完全设置好了,下面可以显示窗口, * 进入gtk_main主循环 */
	gtk_widget_show_all(window);
	
	gtk_main();

	return 0;
}

Makefile

CC = gcc  
MAINC = list.c
EXEC = list

CFLAGS = `pkg-config --cflags --libs gtk+-2.0`

main:  
	$(CC)  $(MAINC)  -o $(EXEC) $(CFLAGS)
clean:
	rm $(EXEC) -rf