GTK+中的构件(GTK+ Widgets)
在本章的GTK+程序设计教程中,我们将带领大家去更深一步的去领略GTK+构件的魅力。
毫无疑问,构件是建立一个GUI应用程序的基础。在很多年来的发展下,一些特定的构件逐渐就成为了大多数编程工具集(toolkits)和几乎所有操作系统的公用标准了。譬如说,按钮,选择框或者是一个滑动条。至于像GTK+这样的编程工具集,一开始他的设计人员所抱的哲学态度是:保持构件的数量在一个合理的范围内。正是由于这一点,越来越多的专用构件,被抽象为通用的构件,供大家使用。
GtkButton
GtkButton 是一种很简单易用的构件,通常被用于触发一个动作。
#include <gtk/gtk.h> int main( int argc, char *argv[]) { GtkWidget *window; GtkWidget *fixed; GtkWidget *button; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "GtkButton"); gtk_window_set_default_size(GTK_WINDOW(window), 230, 150); gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); fixed = gtk_fixed_new(); gtk_container_add(GTK_CONTAINER(window), fixed); button = gtk_button_new_with_label("Quit"); gtk_fixed_put(GTK_FIXED(fixed), button, 50, 50); gtk_widget_set_size_request(button, 80, 35); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(gtk_main_quit), G_OBJECT(window)); g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); gtk_widget_show_all(window); gtk_main(); return 0; }
上面的这个程序示例就是向大家展示一个按钮构件被放置在一个fixed容器构件里。当你按下那个按钮后,程序就会退出。
button = gtk_button_new_with_label("Quit");
上面这段代码生成了一个带有标签的 GtkButton 构件。
g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(gtk_main_quit), G_OBJECT(window));
然后我们再把信号clicked 与这个按钮进行绑定。这个信号会引发函数gtk_main_quit()的调用执行,这个函数的功能正是要使整个程序终止退出。
GtkCheckButton
GtkCheckButton 同样也是一个构件,他有两种状态。“开”和“关”,开表示一个可见的复选标记。
#include <gtk/gtk.h> void toggle_title(GtkWidget *widget, gpointer window) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { gtk_window_set_title(window, "GtkCheckButton"); } else { gtk_window_set_title(window, ""); } } int main(int argc, char** argv) { GtkWidget *window; GtkWidget *frame; GtkWidget *check; 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), 230, 150); gtk_window_set_title(GTK_WINDOW(window), "GtkCheckButton"); frame = gtk_fixed_new(); gtk_container_add(GTK_CONTAINER(window), frame); check = gtk_check_button_new_with_label("Show title"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE); GTK_WIDGET_UNSET_FLAGS(check, GTK_CAN_FOCUS); gtk_fixed_put(GTK_FIXED(frame), check, 50, 50); g_signal_connect_swapped(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); g_signal_connect(check, "clicked", G_CALLBACK(toggle_title), (gpointer) window); gtk_widget_show_all(window); gtk_main(); return 0; }
我们将要展示的功能是:标题栏的显示状态根据构件 GtkCheckButton的状态变化而变化。
check = gtk_check_button_new_with_label("Show title"); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
一个GtkCheckButton 构件被生成了并且默认为已标记(状态为开), 因为我们想一开始标题栏是默认显示的。
GTK_WIDGET_UNSET_FLAGS(check, GTK_CAN_FOCUS);
这行代码是取消了对复选框的默认锁定,这样做的原因很简单,是因为我不大喜欢在复选框上真的“罩”上一个“框”,我个人认为那样不大好看。:)
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) { gtk_window_set_title(window, "GtkCheckButton"); } else { gtk_window_set_title(window, ""); }
这样的话,功能就完成了:标题栏的显示状态根据构件 GtkCheckButton的状态变化而变化。
GtkFrame
GtkFrame 是一种装饰性的框架,还可以为他设置一个标签(可有可无)。
#include <gtk/gtk.h> int main( int argc, char *argv[]) { GtkWidget *window; GtkWidget *table; GtkWidget *frame1; GtkWidget *frame2; GtkWidget *frame3; GtkWidget *frame4; 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), 250, 250); gtk_window_set_title(GTK_WINDOW(window), "GtkFrame"); gtk_container_set_border_width(GTK_CONTAINER(window), 10); table = gtk_table_new(2, 2, TRUE); gtk_table_set_row_spacings(GTK_TABLE(table), 10); gtk_table_set_col_spacings(GTK_TABLE(table), 10); gtk_container_add(GTK_CONTAINER(window), table); frame1 = gtk_frame_new("Shadow In"); gtk_frame_set_shadow_type(GTK_FRAME(frame1), GTK_SHADOW_IN); frame2 = gtk_frame_new("Shadow Out"); gtk_frame_set_shadow_type(GTK_FRAME(frame2), GTK_SHADOW_OUT); frame3 = gtk_frame_new("Shadow Etched In"); gtk_frame_set_shadow_type(GTK_FRAME(frame3), GTK_SHADOW_ETCHED_IN); frame4 = gtk_frame_new("Shadow Etched Out"); gtk_frame_set_shadow_type(GTK_FRAME(frame4), GTK_SHADOW_ETCHED_OUT); gtk_table_attach_defaults(GTK_TABLE(table), frame1, 0, 1, 0, 1); gtk_table_attach_defaults(GTK_TABLE(table), frame2, 0, 1, 1, 2); gtk_table_attach_defaults(GTK_TABLE(table), frame3, 1, 2, 0, 1); gtk_table_attach_defaults(GTK_TABLE(table), frame4, 1, 2, 1, 2); g_signal_connect_swapped(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), G_OBJECT(window)); gtk_widget_show_all(window); gtk_main(); return 0; }
这个示例向我们展示了四种不同风格的frame框架。这些框架构件是利用表格布局法进行布局的。
frame1 = gtk_frame_new("Shadow In"); gtk_frame_set_shadow_type(GTK_FRAME(frame1), GTK_SHADOW_IN);
我们生成了一个GtkFrame构件,并且还为他设置了阴影种类(shadow type)。
GtkLabel
GtkLabel 的功能很明显,是用来显示文字的。
#include <gtk/gtk.h> int main( int argc, char *argv[]) { GtkWidget *window; GtkWidget *label; 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_title(GTK_WINDOW(window), "Nymphetamine"); gtk_window_set_default_size(GTK_WINDOW(window), 350, 400); label = gtk_label_new("Cold was my soul\n\ Untold was the pain\n\ I faced when you left me\n\ A rose in the rain....\n\ So I swore to the razor\n\ That never, enchained\n\ Would your dark nails of faith\n\ Be pushed through my veins again\n\ \n\ Bared on your tomb\n\ I'm a prayer for your loneliness\n\ And would you ever soon\n\ Come above onto me?\n\ For once upon a time\n\ On the binds of your lowliness\n\ I could always find the slot for your sacred key "); gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER); gtk_container_add(GTK_CONTAINER(window), label); g_signal_connect_swapped(window, "destroy", G_CALLBACK (gtk_main_quit), NULL); gtk_widget_show_all(window); gtk_main(); return 0; }
这个示例向我们展示了一首歌的歌词。
label = gtk_label_new("Cold was my soul\n\ Untold was the pain\n\ ...
我们这里生成了一个 GtkLabel 构件。我们利用了换行符来完成多行显示的效果。
gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
哈哈`~我们把标签放在中央,大功告成!
在 GtkLabel 构件中我们也能够使用语法 markup 。(就是用来改变文字样式的语法)下面的这个示例就是展示我们是如何完成这个工作的。
#include <gtk/gtk.h> int main( int argc, char *argv[]) { GtkWidget *window; GtkWidget *label; 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_title(GTK_WINDOW(window), "markup label"); char *str = "ZetCode, Knowledge only matters"; label = gtk_label_new(NULL); gtk_label_set_markup(GTK_LABEL(label), str); gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER); gtk_container_add(GTK_CONTAINER(window), label); gtk_widget_show(label); gtk_window_set_default_size(GTK_WINDOW(window), 300, 100); g_signal_connect(window, "destroy", G_CALLBACK (gtk_main_quit), NULL); gtk_widget_show(window); gtk_main(); return 0; }
这个例子是,我们让一部分文字有突出的效果。
char *str = "<b>ZetCode</b>, Knowledge only matters";
这就是我们要显示的文字内容。
label = gtk_label_new(NULL); gtk_label_set_markup(GTK_LABEL(label), str);
我们生成了一个空的标签构件,然后把样式化的文字(markup text)添加到标签构件里。大功再次告成! -_-!