GTK+入门教程
{
https://blog.csdn.net/ygyoe/article/details/79654057
}
GTK+入门教程(一)
1. 显示一个窗口
#include <gtk/gtk.h>
int main(int argc, char *argv[])
{
GtkWidget *window;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_widget_show(window);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_main();
return 0;
}
这个最基本的框架,语句含义如下:
//生成一个样式为GTK_WINDOW_TOPLEVEL的窗口
gtk_window_new(GTK_WINDOW_TOPLEVEL);
//显示生成的这个窗口
gtk_widget_show(window);
//将窗口的destroy消息绑定处理函数gtk_main_quit
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
// 进入消息循环。
gtk_main();
2. 窗口和图标
注意:与Windows不一样,GTK+的图标不需要单独的ICO文件;下面代码就是使用普通的png文件生成的图标。
#include <gtk/gtk.h>
GdkPixbuf *create_pixbuf(const gchar * filename)
{
GdkPixbuf *pixbuf;
GError *error = 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; GdkPixbuf *icon;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Icon");
gtk_window_set_default_size(GTK_WINDOW(window), 230, 150);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
icon = create_pixbuf("demo.png");
gtk_window_set_icon(GTK_WINDOW(window), icon);
gtk_widget_show(window);
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_object_unref(icon);
gtk_main();
return 0;
}
gtk_window_set_title,gtk_window_set_default_size,gtk_window_set_position 分别设置窗口的标题,窗口的初始长度和宽度,以及初始位置。gtk_window_set_icon设置程序的图标。
3. tooltip(提示信息)和ATL快捷操作
#include <gtk/gtk.h>
void print_msg(GtkWidget *widget, gpointer window) {
g_printf("Button clicked\n");
}
int main(int argc, char *argv[])
{
GtkWidget *window; GtkWidget *button; GtkWidget *halign;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Mnemonic");
gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
gtk_container_set_border_width(GTK_CONTAINER(window), 15);
//button = gtk_button_new_with_label("Button");
button =gtk_button_new_with_mnemonic("_Button");
gtk_widget_set_tooltip_text(button, "Button widget");
g_signal_connect(button, "clicked", G_CALLBACK(print_msg), NULL);
halign = gtk_alignment_new(0, 0, 0, 0);
gtk_container_add(GTK_CONTAINER(halign), button);
gtk_container_add(GTK_CONTAINER(window), halign);
gtk_widget_show_all(window);
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_main();
return 0;
}
采用gtk_button_new_with_label生成的button不会响应ATL键,也不会将“_”解释为添加下划线。要实现下划线和响应ATL的功能,需要使用gtk_button_new_with_mnemonic函数。函数gtk_widget_set_tooltip_text添加tooltip。
g_signal_connect(button, "clicked", G_CALLBACK(print_msg), NULL);给控件button添加了处理消息"clicked"的回调函数print_msg。
gtk_alignment_new 和gtk_container_add设置layout布局的函数,下一节会详细介绍。
4. 菜单操作
4.1 添加1个菜单
#include <gtk/gtk.h>
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *menubar;
GtkWidget *fileMenu;
GtkWidget *fileMi;
GtkWidget *quitMi;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
gtk_window_set_title(GTK_WINDOW(window), "Simple menu");
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(window), vbox);
menubar = gtk_menu_bar_new();
fileMenu = gtk_menu_new();
fileMi = gtk_menu_item_new_with_label("File");
quitMi = gtk_menu_item_new_with_label("Quit");
gtk_menu_item_set_submenu(GTK_MENU_ITEM(fileMi), fileMenu);
gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), quitMi);
gtk_menu_shell_append(GTK_MENU_SHELL(menubar), fileMi);
gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(G_OBJECT(quitMi), "activate", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
4.2 使用子菜单
#include <gtk/gtk.h>
int main(int argc, char *argv[])
{
GtkWidget *window; GtkWidget *vbox;
GtkWidget *menubar;
GtkWidget *fileMenu;
GtkWidget *imprMenu;
GtkWidget *sep;
GtkWidget *fileMi;
GtkWidget *imprMi;
GtkWidget *feedMi;
GtkWidget *bookMi;
GtkWidget *mailMi;
GtkWidget *quitMi;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
gtk_window_set_title(GTK_WINDOW(window), "Submenu");
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(window), vbox);
menubar = gtk_menu_bar_new();
fileMenu = gtk_menu_new();
fileMi = gtk_menu_item_new_with_label("File");
imprMenu = gtk_menu_new();
imprMi = gtk_menu_item_new_with_label("Import");
feedMi = gtk_menu_item_new_with_label("Import news feed...");
bookMi = gtk_menu_item_new_with_label("Import bookmarks...");
mailMi = gtk_menu_item_new_with_label("Import mail...");
gtk_menu_item_set_submenu(GTK_MENU_ITEM(imprMi), imprMenu);
gtk_menu_shell_append(GTK_MENU_SHELL(imprMenu), feedMi);
gtk_menu_shell_append(GTK_MENU_SHELL(imprMenu), bookMi);
gtk_menu_shell_append(GTK_MENU_SHELL(imprMenu), mailMi);
sep = gtk_separator_menu_item_new();
quitMi = gtk_menu_item_new_with_label("Quit");
gtk_menu_item_set_submenu(GTK_MENU_ITEM(fileMi), fileMenu);
gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), imprMi);
gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), sep);
gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), quitMi);
gtk_menu_shell_append(GTK_MENU_SHELL(menubar), fileMi);
gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(G_OBJECT(quitMi), "activate", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
4.3 弹出式菜单
#include <gtk/gtk.h>
int show_popup(GtkWidget *widget, GdkEvent *event)
{
const gint RIGHT_CLICK = 3;
if (event->type == GDK_BUTTON_PRESS)
{
GdkEventButton *bevent = (GdkEventButton *) event;
if (bevent->button == RIGHT_CLICK)
{
gtk_menu_popup(GTK_MENU(widget), NULL, NULL, NULL, NULL, bevent->button, bevent->time);
}
return TRUE;
}
return FALSE;
}
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *ebox;
GtkWidget *pmenu;
GtkWidget *hideMi;
GtkWidget *quitMi;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
gtk_window_set_title(GTK_WINDOW(window), "Popup menu");
ebox = gtk_event_box_new();
gtk_container_add(GTK_CONTAINER(window), ebox);
pmenu = gtk_menu_new();
hideMi = gtk_menu_item_new_with_label("Minimize");
gtk_widget_show(hideMi);
gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), hideMi);
quitMi = gtk_menu_item_new_with_label("Quit");
gtk_widget_show(quitMi);
gtk_menu_shell_append(GTK_MENU_SHELL(pmenu), quitMi);
g_signal_connect_swapped(G_OBJECT(hideMi), "activate", G_CALLBACK(gtk_window_iconify), GTK_WINDOW(window));
g_signal_connect(G_OBJECT(quitMi), "activate", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect_swapped(G_OBJECT(ebox), "button-press-event", G_CALLBACK(show_popup), pmenu);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
4.4 图像菜单和快捷键
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *menubar;
GtkWidget *fileMenu;
GtkWidget *fileMi;
GtkWidget *newMi;
GtkWidget *openMi;
GtkWidget *quitMi;
GtkWidget *sep;
GtkAccelGroup *accel_group = NULL;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
gtk_window_set_title(GTK_WINDOW(window), "Images");
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(window), vbox);
menubar = gtk_menu_bar_new();
fileMenu = gtk_menu_new();
accel_group = gtk_accel_group_new();
gtk_window_add_accel_group(GTK_WINDOW(window), accel_group);
fileMi = gtk_menu_item_new_with_mnemonic("_File");
newMi = gtk_image_menu_item_new_from_stock(GTK_STOCK_NEW, NULL);
openMi = gtk_image_menu_item_new_from_stock(GTK_STOCK_OPEN, NULL);
sep = gtk_separator_menu_item_new();
quitMi = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, accel_group);
gtk_widget_add_accelerator(quitMi, "activate", accel_group, GDK_q, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(fileMi), fileMenu);
gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), newMi);
gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), openMi);
gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), sep);
gtk_menu_shell_append(GTK_MENU_SHELL(fileMenu), quitMi);
gtk_menu_shell_append(GTK_MENU_SHELL(menubar), fileMi);
gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(G_OBJECT(quitMi), "activate", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
4.5 使用工具条
#include <gtk/gtk.h>
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *toolbar;
GtkToolItem *newTb;
GtkToolItem *openTb;
GtkToolItem *saveTb;
GtkToolItem *sep;
GtkToolItem *exitTb;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
gtk_window_set_title(GTK_WINDOW(window), "toolbar");
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(window), vbox);
toolbar = gtk_toolbar_new();
gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS);
newTb = gtk_tool_button_new_from_stock(GTK_STOCK_NEW);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), newTb, -1);
openTb = gtk_tool_button_new_from_stock(GTK_STOCK_OPEN);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), openTb, -1);
saveTb = gtk_tool_button_new_from_stock(GTK_STOCK_SAVE);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), saveTb, -1);
sep = gtk_separator_tool_item_new();
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), sep, -1);
exitTb = gtk_tool_button_new_from_stock(GTK_STOCK_QUIT);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), exitTb, -1);
gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 5);
g_signal_connect(G_OBJECT(exitTb), "clicked", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
4.6 复选框样式菜单和状态条
#include <gtk/gtk.h>
void toggle_statusbar(GtkWidget *widget, gpointer statusbar)
{
if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)))
{
gtk_widget_show(statusbar);
}
else
{
gtk_widget_hide(statusbar);
}
}
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *menubar;
GtkWidget *viewmenu;
GtkWidget *view;
GtkWidget *tog_stat;
GtkWidget *statusbar;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
gtk_window_set_title(GTK_WINDOW(window), "GtkCheckMenuItem");
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(window), vbox);
menubar = gtk_menu_bar_new();
viewmenu = gtk_menu_new();
view = gtk_menu_item_new_with_label("View");
tog_stat = gtk_check_menu_item_new_with_label("View statusbar");
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(tog_stat), TRUE);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(view), viewmenu);
gtk_menu_shell_append(GTK_MENU_SHELL(viewmenu), tog_stat);
gtk_menu_shell_append(GTK_MENU_SHELL(menubar), view);
gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
statusbar = gtk_statusbar_new();
gtk_box_pack_end(GTK_BOX(vbox), statusbar, FALSE, TRUE, 0);
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(G_OBJECT(tog_stat), "activate", G_CALLBACK(toggle_statusbar), statusbar);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
4.7 简单的重复和撤销操作
#include <gtk/gtk.h>
void undo_redo(GtkWidget *widget, gpointer item)
{
static gint count = 2;
const gchar *name = gtk_widget_get_name(widget);
if (g_strcmp0(name, "undo") )
{
count++;
}
else
{
count--;
}
if (count < 0)
{
gtk_widget_set_sensitive(widget, FALSE);
gtk_widget_set_sensitive(item, TRUE);
}
if (count > 5)
{
gtk_widget_set_sensitive(widget, FALSE);
gtk_widget_set_sensitive(item, TRUE);
}
}
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *toolbar;
GtkToolItem *undo;
GtkToolItem *redo;
GtkToolItem *sep;
GtkToolItem *exit;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
gtk_window_set_title(GTK_WINDOW(window), "Undo redo");
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(window), vbox);
toolbar = gtk_toolbar_new();
gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS);
gtk_container_set_border_width(GTK_CONTAINER(toolbar), 2);
undo = gtk_tool_button_new_from_stock(GTK_STOCK_UNDO);
gtk_widget_set_name(GTK_WIDGET(undo), "undo");
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), undo, -1);
redo = gtk_tool_button_new_from_stock(GTK_STOCK_REDO);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), redo, -1);
sep = gtk_separator_tool_item_new();
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), sep, -1);
exit = gtk_tool_button_new_from_stock(GTK_STOCK_QUIT);
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), exit, -1);
gtk_box_pack_start(GTK_BOX(vbox), toolbar, FALSE, FALSE, 0);
g_signal_connect(G_OBJECT(undo), "clicked", G_CALLBACK(undo_redo), redo);
g_signal_connect(G_OBJECT(redo), "clicked", G_CALLBACK(undo_redo), undo);
g_signal_connect(G_OBJECT(exit), "clicked", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
下一篇: GTK+中的布局