gtk_overviewGTK入门

GTK入门

Gtk+概述

GUI

GUI 含义: (Graphics User Interface)

图形用户界面, 是计算机与使用者之间的对话接口, 是计算机重要的组成部分, 比如说咱们使用电脑或手机看到的 Windows 的桌面或 wps 软件显示的窗口界面等都是 GUI, 都是图形界面开发出来的图形界面的软件。

GUI 组成 : 桌面、 视窗、 菜单、 按钮、 图标等等

GUI 特点 :

可以使操作更加简单, 更加快捷、 更加人性化。 八十岁的老奶奶也会使用智能手机

早期的操作系统比如 DOS, 属于 CUI(Command line User Interface)

命令行模式的人机接口。

GTK+

GTK+是一套在 GIMP 的基础上发展而来的高级的、 可伸缩的现代化、 跨平台图形工具包, 它可以很方便地制作图形交互界面( GUI )。

GTK+特点:

稳定、 跨平台、 多种语言绑定、 接口丰富、 与时俱进、 算法丰富、 移动嵌入式应用广泛

https://www.gtk.org/

环境搭建

linux 下

1、安装

gtk+2.0所需的所有文件统通下载安装完毕

sudo apt-get install libgtk2.0*

2、测试

运行:

pkg-config --cflags --libs gtk+-2.0

现象:

-pthread -I/usr/local/include/gio-unix-2.0/ -I/usr/local/include/atk-1.0 -I/usr/local/include/glib-2.0 -I/usr/local/lib/glib-2.0/include -I/usr/include/gtk-2.0 -I/usr/include/pango-1.0 -I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/freetype2 -I/usr/include/pixman-1 -I/usr/include/libpng12

说明成功

GTK+数据类型之C语言类型

  • 整数类型:gint8guint8gint16guint16gint32guint32gint64guint64。不是所有的平台都提供64位整型
  • 整数类型 gshortglonggintshortlongint 相同
  • 布尔类型 gbooleangboolean 可以取两个值:TRUEFALSE
  • 字符型 gcharchar 相同
  • 浮点型 gfloatgdoublefloatdouble 完全等价
  • 指针 gpointer 对应于标准C的 void *
  • const gpointer 对于于标准C的 const void *

GTK+的面向对象机制

面向对象编程语言(如C++、Java)把 数据 和 对数据的操作封装在一起构成,由 来 产生对象,由对象来构建程序。类中对数据的操作由函数来完成,这种函数被称为成员函数方法

面向对象语言通过继承、重载、多态等机制大大增强软件的可重用性可维护性。C语言虽然不是面向对象语言,但GTK+以及建立在其上的GNOME库却使C语言模拟出了一些典型的面向对象机制,如封装、继承和多态。

对象的一个主要特性是将数据和对数据的操作封装在一起,受保护的私有数据只能通过成员函数才能访问和修改。GTK+使用C语言的结构体来模拟对象,虽然有些缺陷但基本模拟出了对象的基本特征。

有了对象作为基础,通过在对象中加入新的数据和对这些数据进行操作的函数,就实现了继承。被 继承的类(类相当于一种自定义数据类型,由类来定义对象)称为父类基类,由基础类派生出来的类称为子类派生类。子类继承了父类的数据和对这些数据进行 操作的成员函数,并加入了新的数据和成员函数,实现了对原有父类的重用和扩展,从而实现了可重用性可扩展性

GTK+中有一个类,它是所有其他类的父类,这个类是GtkObject。GTK+中最常用的按钮控件也是一个类,它继承自GtkObject。它与GtkObject的继承关系是:

GtkObject ->GtkWidget ->GtkContainer ->GtkBin ->GtkButton

对象(类)是由结构体模拟的,每一个子类所在的结构体都包含了父类的结构体,子类结构体的第一个成员是其父类结构体,示例代码如下:

struct GtkObject 
{//...
};struct GtkWidget 
{GtkObject object;//..
};struct GtkContainer 
{GtkWidget widget;//...
};struct GtkBin 
{GtkContainer container;//...
};

每个子类都包含了其父类的所有数据,并且父类的数据位于子类结构体的开始。对于一个GtkButton 类型的 button 控件变量(它其实是一个指向GtkButton 结构体的指针),通过宏 GTKBIN(button) 就得到了其父类(GTK+预定义的 宏GTKBIN其实是进行了强制类型转换,把一个 GtkButton 类型的指针强制转化为 GtkBin 类型的指针)

test.c 测试程序 :

#include<stdio.h>
#include<stdlib.h>#define FATHER(child) (struct Father *)(child)void print1(int i)
{printf("this is father and i = %d\n", i);
}void print2(int i)
{printf("this is child  and i = %d\n", i);
}// 模拟父类 
struct Father 
{// 成员变量 int a;// 成员函数, 指向函数的指针void (*pointer1_to_function)(int);
};// 模拟子类
struct Child 
{// 模拟继承 , 结构体 Fatherstruct Father f;int b;void (* pointer2_to_function)(int);
};void father_member_funtion(struct Father *f, char *string)
{printf("\n");f->pointer1_to_function(f->a);printf("%s\n\n", string);
}int main()
{// 定义指向结构体 Child 的指针struct Child *p_child;p_child = (struct Child *)malloc(sizeof(struct Child));// 成员初始化p_child->f.a = 10;p_child->f.pointer1_to_function = print1;p_child->b = 20;p_child->pointer2_to_function = print2;// 调用成员函数p_child->pointer2_to_function(p_child->b);// 将指针p_child强制转换为指 向Father结构体的指针struct Father *p_father = FATHER(p_child);p_father->pointer1_to_function(p_father->a);// 实现方法, 避免了在结构体Father中保存函数指针father_member_funtion(p_father, "hello");return 0;
}

GTK+定义了很多生成对象 或 对对象进行操作的函数

// 创建了一个对象
GtkWidget *button;button = gtk_button_new_with_label("label");

所有创建对象的函数在其名称上都有“ new ”这个词。

// 创建了一个显示文本的按钮
gtk_button_new_with_label

可以当作父类来对待所有子类(多态),按钮 button 的真正类型是 GtkButton,却也可以作为一个指向 GtkWidget 类型的指针。

当调用一个函数对一个对象进行相关操作时,该对象的地址作为第一个参数传给函数。

//显示按钮的函数
gtk_widget_show(button);

button 是一个指向 GtkWidget 结构体的指针,它也表示一个按钮控件。

面向对象语言中子类可以调用父类的函数,在 GTK+ 中只要使用一些宏将子类强制转换为父类即可。

gtk_container_add(GTK_CONTAINER(window), button);

gtk_container_add 函数是类 GtkContainer 的一个函数,而 window 代表一个窗口,它是 GtkWindow 类型的指针。

GtkWindow 是 GtkContainer 的子类,也就是 GtkWindow 继承自 GtkContainer,当然它们都是从 GtkObject 派生出来的,GtkObject 是它们的祖先:

GtkObject -> GtkWidget -> GtkContainer -> GtkBin -> GtkWindow

空白窗口

栗子 : first_window.c

#include <gtk/gtk.h>int main(int argc, char *argv[])
{// 初始化,必须在控件定义之前使用gtk_init(&argc, &argv&);/* 创建窗口(参数有两种形式)* GTK_WINDOW_TOPLEVEL:顶层窗口,包含窗口的标题栏和边框,有最大化最小化* GTK_WINDOW_POPUP:弹出窗口, 没有窗口的标题栏和边框,不能改变大小和移动*/GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);// 显示窗口控件gtk_widget_show(window);    // 主事件循环,程序也必须要这个    gtk_main();return 0;
}

Makefile

CC = gcc
MAINC = first_window.c
EXEC = first_windowCFLAGS = `pkg-config --cflags --libs gtk+-2.0`main:$(CC) $(MAINC) -o $(EXEC) $(CFLAGS)clean:rm $(EXEC) -rf

GTK 程序的基本框架 :

#include <gtk/gtk.h>int main(int argc, char *argv[])
{// 初始化,必须在控件定义之前使用gtk_init(&argc, &argv&);//代码// 主事件循环,程序也必须要这个    gtk_main();return 0;
}

GtkWidget 是 GTK+控件类型, GtkWidget * 能指向任何控件的指针类型。

GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

创建一个窗口并返回这个窗口的控件指针

gtk_window_new()

窗口的创建 :

/*
GtkWindowType 是一个枚举, 有两种情况:
GTK_WINDOW_TOPLEVEL: 有边框
GTK_WINDOW_POPUP: 没边框
*/
GtkWidget *gtk_window_new(GtkWindowType type);

标题的设置 :

void gtk_window_set_title(GtkWindow *window, const gchar *title);

窗口最小大小的设置

void gtk_widget_set_size_request(GtkWidget *widget,gint width,gint height);

窗口伸缩设置( FALSE 为不可伸缩 )

void gtk_window_set_resizable(GtkWindow *window, gboolean resizable);

显示或隐藏所有控件 :

void gtk_widget_show_all(GtkWidget *widget);void gtk_widget_hide_all(GtkWidget *widget);

窗口在显示器位置的设置

/*
position 常用有 4 种情况:
GTK_WIN_POS_NONE: 不固定
GTK_WIN_POS_CENTER: 居中
GTK_WIN_POS_MOUSE: 出现在鼠标位置
GTK_WIN_POS_CENTER_ALWAYS: 窗口总是居中
*/
void gtk_window_set_position(GtkWindow *window, GtkWindowPosition position);

栗子 : Window.c

#include <gtk/gtk.h>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 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_set_size_request(Window, 400, 300);//设置窗口固定gtk_window_set_resizable(GTK_WINDOW(Window), FALSE);//"destroy" 和 gtk_main_quit 连接g_signal_connect(Window, "destroy", G_CALLBACK(gtk_main_quit), NULL);// 显示窗口全部控件gtk_widget_show_all(Window);//gtk_widget_hide_all(window);    // 隐藏窗口//主事件循环gtk_main();return 0;
}

带按钮的窗口

控件的介绍 :

控件是对数据和方法的封装。 控件有自己的属性和方法。 属性是指控件的特征。 方法是指控件的一些简单而可见的功能。

控件的分类: 容器控件, 非容器控件。

容器控件: 它可以容纳别的控件。 容器控件分为两类, 一类只能容纳一个控件, 如窗口, 按钮; 另一类能容纳多个控件, 如布局控件。

非容器控件: 它不可以容纳别的控件, 如标签、 行编辑。

// 创建一个带内容的按钮
GtkWidget *gtk_button_new_with_label(const gchar *label );
//获得按钮上面的文本内容
const gchar *gtk_button_get_label(GtkButton *button );
// 把控件添加到窗口容器里
// container: 容纳控件的容器
// widget: 要添加的控件
void gtk_container_add(GtkContainer *container, GtkWidget *widget);

栗子 : window_with_button.c

#include <gtk/gtk.h> // 头文件int main( int argc,char *argv[] )
{gtk_init(&argc, &argv); // 初始化GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); // 创建顶层窗口// 设置窗口边框的宽度(窗口里的控件与窗口边框间隔为 15)gtk_container_set_border_width(GTK_CONTAINER(window), 15);// 创建按钮, 文本信息GtkWidget *button = gtk_button_new_with_label("cpuocde");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(button);// gtk_widget_show(window);gtk_widget_show_all(window); // 显示窗口全部控件gtk_main(); // 主事件循环return 0;
}

信号与回调函数机制

GTK+采用了信号回调函数来处理窗口外部传来的事件、 消息或信号。 当信号发生时, 程序自动调用为信号连接的回调函数。

窗口关闭时触发的常用信号: destroy , delete-event

操作按钮触发的常用信号: clicked, pressedreleased

/** 信号与回调函数的连接* instance: 信号的发出者* detailed_signal: 要连接信号的名称* c_handler: 回调函数的名称, 需要用 G_CALLBACK()进行转换* data: 传递给回调函数的参数*/
gulong g_signal_connect(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data );

回调函数的定义

//信号连接函数
g_signal_connect(button, "pressed", G_CALLBACK(callback), NULL);
// 回调函数
// button: 信号的发出者
// user_data: 传给回调函数的数据
void callback( GtkButton *button, gpointer user_data );

栗子 : signal.c

#include <gtk/gtk.h>    // 头文件// 按钮按下的处理函数, gpointer 相当于 void *
void deal_pressed(GtkButton *button, gpointer user_data)
{// 获得按钮的文本信息const gchar *text = gtk_button_get_label( button );// g_print() 相当于C语言的 printf(), gchar相当于charg_print("button_text = %s; user_data = %s\n", text, (gchar *)user_data);
}int main( int argc,char *argv[] )
{gtk_init(&argc, &argv);        // 初始化// 创建顶层窗口GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); // 设置窗口边框的宽度(窗口里的控件与窗口边框间隔为15)gtk_container_set_border_width(GTK_CONTAINER(window), 15);/* 当窗口关闭时,窗口会触发destroy信号,* 自动调用gtk_main_quit()结束程序运行。*/g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);//创建按钮GtkWidget *button = gtk_button_new_with_label("cpucode");// 把按钮放入窗口(窗口也是一种容器)gtk_container_add(GTK_CONTAINER(window), button);    /* 按钮按下(pressed)后会自动调用 deal_pressed()* "is pressed"是传给deal_pressed()的数据*/g_signal_connect(button, "pressed", G_CALLBACK(deal_pressed), "is pressed");gtk_widget_show_all(window);    // 显示窗口全部控件gtk_main();        // 主事件循环return 0;
}

常用布局

设定控件在整个窗口中的位置和尺寸

常用的布局方式

  • 水平布局 GtkHBox
  • 垂直布局 GtkVBox
  • 表格布局 GtkTable
  • 固定布局 GtkFixed
水平布局
// 创建水平布局容器
// homogeneous: 容器内控件是否均衡排放(大小一致)
// spacing: 控件之间的间隔
GtkWidget *gtk_hbox_new(gboolean homogeneous, gint spacing);
// 添加控件到布局容器中
gtk_container_add(GtkContainer *container, GtkWidget *widget );

栗子 : hbox.c 横向布局

#include <gtk/gtk.h>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 layout");//设置窗口边框的宽度gtk_container_set_border_width(GTK_CONTAINER(window), 15);g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);/** 创建横向盒状容器* GtkWidget *gtk_vbox_new(gboolean homogeneous, gint spacing);* homogeneous:容器内控件是否均衡排放(TRUE or FALSE)* spacing: 控件之间的间隔*/GtkWidget *hbox = gkt_hbox_new(TRUE, 10);//把横向容器放到窗口gtk_container_add(GTK_CONTAINER(window), hbox);//button1GtkWidget *button = gtk_button_new_with_label("button1");// 按钮添加到布局容器里gtk_container_add(GTK_CONTAINER(hbox), button);// button2button = gtk_button_new_with_label("button2");// 按钮添加到布局容器里gtk_container_add(GTK_CONTAINER(hbox), button);// button3button = gtk_button_new_with_label("button3");gtk_container_add(GTK_CONTAINER(hbox), button);     // 按钮添加到布局容器里gtk_widget_show_all(window);    // 显示窗口控件gtk_main();     // 主事件循环return 0; 
}

垂直布局

垂直布局容器的操作和水平布局的操作几乎是一样

//创建垂直布局容器
gtk_vbox_new()
//标签的创建
GtkWidget *gtk_label_new(const gchar *str);
// 设置标签的内容
void gtk_label_set_text(GtkLabel *label, const gchar *str);
//获得标签的内容
const gchar *gtk_label_get_label(GtkLabel *label );

栗子 : vbox.c 纵向布局

#include <gtk/gtk.h>    // 头文件/** 设置label字体的大小* label: 需要操作的label* size:  字体的大小*/
void set_label_font_size(GtkWidget *label, int size)
{// 字体指针PangoFontDescription *font;//参数为字体名字font = pango_font_description_from_string("cpucode");// #define PANGO_SCALE 1024// 设置字体大小   pango_font_description_set_size(font, size * PANGO_SCALE);// 改变label的字体大小gtk_widget_modify_font(label, font);// 释放字体指针分配的空间pango_font_description_free(font);
}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 vertical layout");g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);// 设置窗口边框的宽度gtk_container_set_border_width(GTK_CONTAINER(window), 15);// 创建纵向盒状容器GtkWidget *vbox = gtk_vbox_new(TRUE, 15);// 把纵向盒状容器放入窗口gtk_container_add(GTK_CONTAINER(window), vbox);//label one// 创建标签GtkWidget *label = gtk_label_new("label one");// 设置label字体大小,这个为自定义的函数set_label_font_size(label, 30);// 将按钮放在布局容器里gtk_container_add(GTK_CONTAINER(vbox), label);// label twolabel = gtk_label_new("text");gtk_label_set_text(GTK_LABEL(label), "label two");          // 设置label的内容const char *str = gtk_label_get_label( GTK_LABEL(label) ); // 获得标签的内容g_print("str = %s\n", str);// 设置label字体大小,这个为自定义的函数set_label_font_size(label, 30);gtk_container_add(GTK_CONTAINER(vbox), label);         // 将按钮放在布局容器里// label threelabel = gtk_label_new("label three");set_label_font_size(label, 30);    // 设置label字体大小,这个为自定义的函数gtk_container_add(GTK_CONTAINER(vbox), label);         // 将按钮放在布局容器里gtk_widget_show_all(window);    // 显示窗口控件// 主事件循环gtk_main();return 0;
}

Makefile

CC = gcc  
MAINC = vbox.c
EXEC = vboxCFLAGS = `pkg-config --cflags --libs gtk+-2.0`main:  $(CC) $(MAINC) -o $(EXEC) $(CFLAGS)
clean:rm $(EXEC) -rf

表格布局
// 创建表格布局容器
// rows:行数
// coumns:列数
// homogeneous: 容器内表格的大小是否一致
GtkWidget*gtk_table_new(guint rows, guint columns, gboolean homogeneous );
// 添加控件到布局容器中
// table: 要容纳控件的容器
// widget: 被容纳控件
// 后四个参数 : 控件摆放的坐标
void gtk_table_attach_defaults(GtkTable *table, GtkWidget *widget, guint left_attach, guint right_attach,guint top_attach, guint bottom_attach );

image-20200806132252551

栗子 : table.c 表格布局

#include <gtk/gtk.h>    // 头文件// button 1, button 2处理函数
void callback(GtkButton *button, gpointer data)
{g_print("%s is clicked!\n", (gchar *)data);
}// close button处理函数
void close_window(GtkWidget *widget, GdkEvent *event, 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 table");g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);// 设置窗口边框的宽度gtk_container_set_border_width(GTK_CONTAINER(window), 15);/** 创建表格布局容器* GtkWidget * gtk_table_new(guint rows, guint columns, gboolean homogeneous);* rows:         行数* coumns:       列数* homogeneous: 容器内控件是否均衡排放(TRUE or FALSE)*/GtkWidget *table = gtk_table_new(2, 2, TRUE);gtk_container_add(GTK_CONTAINER(window), table); // 容器加入窗口// button 1GtkWidget *button = gtk_button_new_with_label("buttton 1");g_signal_connect(button, "pressed", G_CALLBACK(callback), "button 1");gtk_table_attach_defaults(GTK_TABLE(table), button, 0, 1, 0, 1);// 把按钮加入布局// button 2button = gtk_button_new_with_label("button 2");g_signal_connect(button, "pressed", G_CALLBACK(callback), "button 2");gtk_table_attach_defaults(GTK_TABLE(table), button, 1, 2, 0, 1);// close buttonbutton = gtk_button_new_with_label("close");g_signal_connect(button, "pressed", G_CALLBACK(close_window), NULL);gtk_table_attach_defaults(GTK_TABLE(table), button, 0, 2, 1, 2);gtk_widget_show_all(window);    // 显示窗口控件gtk_main();     // 主事件循环return 0;
}

Makefile

CC = gcc
MAINC = table.c
EXEC = tableCFLAGS = `pkg-config --cflags --libs gtk+-2.0`main:$(CC) $(MAINC) -o $(EXEC) $(CFLAGS)
clean:rm $(EXEC) -rf

固定布局
//创建固定布局容器
GtkWidget *gtk_fixed_new(void);
// 添加控件到容器中
// fixed: 要容纳控件的容器
// widget: 被容纳控件
// x, y: 控件摆放位置的起点坐标
void gtk_fixed_put( GtkFixed *fixed, GtkWidget *widget, gint x, gint y );

栗子 : fixed.c 固定布局

#include <gtk/gtk.h> 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"); // 设置标题// 为窗口的 "destroy" 事件设置一个信号处理函数  g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);GtkWidget *fixed = gtk_fixed_new();     //创建一个固定容器gtk_container_add(GTK_CONTAINER (window), fixed); // 固定放进窗口GtkWidget *button; int i; for(i = 1 ; i <= 3 ; i++){button = gtk_button_new_with_label ("Press me");  // 创建按钮// 将按钮组装到一个固定容器的窗口中gtk_fixed_put(GTK_FIXED(fixed), button, i * 50, i * 50); }gtk_widget_show_all(window);  // 显示所有控件gtk_main();  //进入事件循环 return 0; 
}

Makefile

CC = gcc
MAINC = fixed.c
EXEC = fixedCFLAGS = `pkg-config --cflags --libs gtk+-2.0`main:$(CC) $(MAINC) -o $(EXEC) $(CFLAGS)
clead:rm $(EXEC) -rf

行编辑

//行编辑的创建
GtkWidget *gtk_entry_new(void);
//显示模式(FALSE 为密码模式)
void gtk_entry_set_visibility(GtkEntry *entry, gboolean visible );
// 获得文本内容
const gchar *gtk_entry_get_text(GtkEntry *entry );
//设置行编辑的内容
void gtk_entry_set_text(GtkEntry *entry, const gchar *text);
//常用信号:按回车键触发
activate

栗子 : entry.c 行编辑

#include <gtk/gtk.h> // 按Enter,获取行编辑的内容
void enter_callback( GtkWidget *widget, gpointer entry ) 
{ const gchar *entry_text; // 获得文本内容entry_text = gtk_entry_get_text(GTK_ENTRY(entry)); printf("Entry contents: %s\n", entry_text); 
}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 Entry");         // 设置标题g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);GtkWidget *vbox = gtk_vbox_new(TRUE, 5);     // 垂直布局,控件均衡摆放,控件间距为0gtk_container_add(GTK_CONTAINER(window), vbox);     // 容器放入窗口GtkWidget *entry = gtk_entry_new();  // 创建行编辑     gtk_container_add(GTK_CONTAINER(vbox), entry);     // 加入垂直布局里gtk_entry_set_max_length(GTK_ENTRY(entry), 100);     // 设置行编辑显示最大字符的长度gtk_entry_set_text(GTK_ENTRY(entry), "hello word");  // 设置内容gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE);      // 密码模式/* 如果我们想在用户输入文本时进行响应,可以为 activate 设置回调函数。* 当用户在文本输入构件内部按回车键时引发Activate信号;*/g_signal_connect(entry, "activate", G_CALLBACK(enter_callback), entry);GtkWidget *hbox = gtk_hbox_new(TRUE, 0);       // 水平布局容器gtk_container_add(GTK_CONTAINER(vbox), hbox); // 水平布局容器加入垂直布局容器里// "button 1"GtkWidget *button1 = gtk_button_new_with_label("button 1");gtk_container_add(GTK_CONTAINER(hbox), button1); // 按钮1添加到水平布局容器里// "button 2"GtkWidget *button2 = gtk_button_new_with_label("button 2"); gtk_container_add(GTK_CONTAINER(hbox), button2); // 按钮2添加到水平布局容器里// close buttonGtkWidget *button_close = gtk_button_new_with_label("close"); g_signal_connect(button_close, "clicked", G_CALLBACK (gtk_main_quit), NULL); gtk_container_add(GTK_CONTAINER(vbox), button_close); // 关闭按钮添加到垂直布局容器里gtk_widget_show_all(window); // 显示窗口所有控件gtk_main();         // 主事件循环return 0;
}

Makefile

CC = gcc
MAINC = entry.c
EXEC = entryCFLAGS = `pkg-config -cflags --libs gtk+-2.0`main:$(CC) $(MAINC) -o $(EXEC) $(CFLAGS)
clean:rm $(EXEC) -rf

  • @由于个人水平有限, 难免有些错误, 还请指点:
  • @Author: cpu_code
  • @Date: 2020-08-01 17:04:25
  • @LastEditTime: 2020-08-06 18:27:26
  • @FilePath: \notes\GTK\GTK_overview.md
  • @Gitee: https://gitee.com/cpu_code
  • @Github: https://github.com/CPU-Code
  • @CSDN: https://blog.csdn.net/qq_44226094
  • @Gitbook: https://923992029.gitbook.io/cpucode/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/9561.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

gorm-sharding分表插件升级版

代码地址&#xff1a; GitHub - 137/gorm-sharding: Sharding 是一个高性能的 Gorm 分表中间件。它基于 Conn 层做 SQL 拦截、AST 解析、分表路由、自增主键填充&#xff0c;带来的额外开销极小。对开发者友好、透明&#xff0c;使用上与普通 SQL、Gorm 查询无差别.解决了原生s…

传统鞋业如何转型?3D数字化技术让鞋业品牌焕发新机!

数字经济时代&#xff0c;3D数字化技术在各行业都得到广泛应用&#xff0c;这其中&#xff0c;传统的鞋服行业的发展也受到了3D数字化技术的影响&#xff0c;产生了深刻的变化&#xff0c;越来越多的鞋企品牌开始尝试3D数字化营销。 比如&#xff0c;时尚运动品牌VANS就在官网上…

论文AIGC检测让毕业生头疼,如何有效降低AI查重率!

在准备毕业论文的过程中&#xff0c;不知道大家有没有跟我一样&#xff0c;遇到这样棘手的问题。我们都知道在撰写完论文后&#xff0c;进行论文查重是我们必不可少的一步。于是&#xff0c;我拿着论文进行了论文重复率的检测&#xff0c;发现重复率只有2.8%&#xff0c;看到这…

探案录 | KingbaseES+SqlSugar为医疗用户排忧解难

在2024年的初春&#xff0c;某大型三甲医院的CT预约系统上线测试&#xff0c;如同新芽破土&#xff0c;充满了希望与活力。然而&#xff0c;仅仅两天后&#xff0c;一个技术难题如同迷雾中的幽灵&#xff0c;悄然出现&#xff1a;The connection pool has been exhausted…… 福…

三相两电平逆变器的Simulink仿真建模及SPWM

三相两电平逆变器的介绍 三相两电平逆变器的电路结构如下图所示&#xff0c;作为非常基本的电力电子电路&#xff0c;众多教科书中均有对该电路的原理介绍&#xff0c;本文不再对原理进行赘述&#xff0c;主要目的在于提供simulink仿真电路。下图即为三相两电平逆变器电路结构…

图文并茂:解析Spring Boot Controller返回图片的三种方式

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 图文并茂&#xff1a;解析Spring Boot Controller返回图片的三种方式 前言使用Base64编码返回图片使用byte数组返回图片使用Resource对象返回图片图片格式转换与性能对比 前言 在互联网的世界里&…

AI雷达智能销售名片小程序源码系统+企业商城+公司动态 带完整的安装代码包以及安装搭建教程

在数字化时代&#xff0c;企业的销售模式正在经历一场深刻的变革。为了更好地满足市场需求&#xff0c;提升销售效率&#xff0c;罗峰给大家分享一款集AI雷达智能销售名片、企业商城、公司动态于一体的源码系统。该系统不仅配备了完整的安装代码包&#xff0c;还附有详细的安装…

批量自定义重命名,一键添加顺序编号,文件夹管理更高效!

我们经常需要对文件夹进行管理和整理。然而&#xff0c;当面对大量需要改名的文件夹时&#xff0c;手动逐个修改不仅效率低下&#xff0c;还容易出错。那么&#xff0c;有没有一种方法能够批量自定义重命名文件夹&#xff0c;并在名称后自动添加顺序编号呢&#xff1f;答案是肯…

ABC352编程笔记

ABC352 编程笔记 题意&#xff1a;输入&#xff0c;四个数 a , b , c , d a,b,c,d a,b,c,d&#xff0c;若 d d d 在 c , d c,d c,d 之间&#xff0c;则输出 Yes&#xff0c;否则输出 No。 正解&#xff1a;直接判断。 #include <bits/stdc.h> //#define int long lo…

vscode正则匹配技巧

写正则表达式 下面是匹配加粗的单词或空格 \*\*[a-zA-Z\s]*\*\*vscode提取加粗的内容 altenter&#xff0c;再ctrlC复制选中的内容出来

DDD面试题:DDD聚合和表的对应关系是什么 ?(来自蚂蚁面试)

尼恩说在前面&#xff1a; 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如字节、阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格&#xff0c;遇到很多很重要的面试题&#xff1a; DDD 的外部接口调用&#xff0c;应该放在…

深入了解二叉搜索树:原理、操作与应用

文章目录 二叉搜索树二叉搜索树的操作1.查找操作2.插入操作3.查找最大值或者最小值4.删除操作5.前序中序后序遍历 总结 二叉搜索树 形如上图的二叉树就是二叉搜索树&#xff0c;接下来我们来具体阐述一下什么是二叉搜索树。 二叉搜索树的概念&#xff1a;满足左子树的值小于根…

经济学SSCI期刊,中科院3区,IF=2+,难度不大,收稿范围广泛!

一、期刊名称 Information Economics and Policy 二、期刊简介概况 期刊类型&#xff1a;SSCI 学科领域&#xff1a;经济学 影响因子&#xff1a;2.8 中科院分区&#xff1a;3区 出版方式&#xff1a;订阅模式/开放出版 版面费&#xff1a;选择开放出版需支付$3190 三、…

C++ | Leetcode C++题解之第78题子集

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<int> t;vector<vector<int>> ans;void dfs(int cur, vector<int>& nums) {if (cur nums.size()) {ans.push_back(t);return;}t.push_back(nums[cur]);dfs(cur 1, nums);t.po…

yum仓库和NFS网络共享服务

一、yum 1.1yum的定义 yum是一个基于RPM包&#xff0c;构建的软件更新机制&#xff0c;能够自动解决软件包之间的依赖关系。解决了日常工作中的大量查找安装依赖包的时间 为什么会有依赖关系的发生 因为linux本身就是以系统简洁为自身优势&#xff0c;所以在安装操作系统的时…

Docker与Harbor:构建企业级私有Docker镜像仓库

目录 引言 一、本地私有仓库 &#xff08;一&#xff09;基本概述 &#xff08;二&#xff09;搭建本地私有仓库 1.下载registry镜像 2.启动容器 3.上传本地镜像 4.客户端下载镜像 二、Harbor简介 &#xff08;一&#xff09;什么是 Harbor &#xff08;二&#xff…

苹果15能用哪些充电宝?充电宝什么牌子好?好用充电宝排名

随着移动设备的普及和功能的不断强大&#xff0c;我们对于充电宝的需求也越来越高。尤其是对于苹果15用户来说&#xff0c;选择一款兼容性好、性能稳定的充电宝显得尤为重要。在市面上众多充电宝品牌中&#xff0c;如何选择适合苹果15的充电宝&#xff1f;究竟哪个牌子的充电宝…

在线扭蛋机小程序:商家稳占市场的新突破口

近几年&#xff0c;扭蛋机进入了爆发期&#xff0c;动漫、游戏的发展更是推动了市场的发展&#xff0c;我国扭蛋机正在蓬勃发展中。 不过&#xff0c;在市场规模扩大下&#xff0c;扭蛋机行业的竞争力也在同时加大&#xff0c;企业商家需要在市场竞争中寻求发展新思路&#xf…

C#进阶-OleDb操作Excel和数据库

在C#编程中&#xff0c;使用OleDb可以方便地实现对Excel文件和数据库的操作。本文探讨了在C#中使用OleDb技术操作Excel和数据库的策略。文章详述了OleDb的定义、配置环境的步骤&#xff0c;并通过实际代码示例演示了如何高效读写Excel文件和交互数据库。文中还评估了OleDb技术的…

KaiwuDB 参编的《分析型数据库技术要求》标准正式发布

近期&#xff0c;中国电子工业标准化技术协会正式发布团体标准《分析型数据库技术要求》&#xff08;项目号&#xff1a;T-CESA 2023-006&#xff09;。该标准由中国电子技术标准化研究院、KaiwuDB&#xff08;上海沄熹科技有限公司&#xff09; 等国内 16 家企业联合起草&…