Spin Buttons
Spin Button用于让用户在一个范围内的数值中选择一个数字。它包含一个text entry box,并且在entry box旁边有用于上下翻的箭头按钮。entry box也能够直接被编辑。
下面举例说明其用法。
程序运行结果:
/**spinbutton.c/
#include<stdio.h>
#include<gtk/gtk.h>static GtkWidget *spinner1;static void toggle_snap(GtkWidget *widget, GtkSpinButton *spin)
{gtk_spin_button_set_snap_to_ticks(spin, GTK_TOGGLE_BUTTON(widget)->active);
}static void toggle_numeric(GtkWidget *widget, GtkSpinButton *spin)
{gtk_spin_button_set_numeric(spin, GTK_TOGGLE_BUTTON(widget)->active);
}static void change_digits(GtkWidget *widget, GtkSpinButton *spin)
{gtk_spin_button_set_digits(GTK_SPIN_BUTTON(spinner1), gtk_spin_button_get_value_as_int(spin));
}static void get_value(GtkWidget *widget, gpointer data)
{gchar *buf;GtkLabel *label;GtkSpinButton *spin;spin = GTK_SPIN_BUTTON(spinner1);label = GTK_LABEL(g_object_get_data(G_OBJECT(widget), "user_data"));if(GPOINTER_TO_INT(data) == 1)buf = g_strdup_printf("%d", gtk_spin_button_get_value_as_int(spin));elsebuf = g_strdup_printf("%0.*f", spin->digits, gtk_spin_button_get_value(spin));gtk_label_set_text(label, buf);g_free(buf);
}int main(int argc, char *argv[])
{GtkWidget *window;GtkWidget *frame;GtkWidget *hbox;GtkWidget *main_vbox;GtkWidget *vbox;GtkWidget *vbox2;GtkWidget *spinner2;GtkWidget *spinner;GtkWidget *button;GtkWidget *label;GtkWidget *val_label;GtkAdjustment *adj;gtk_init(&argc, &argv);window = gtk_window_new(GTK_WINDOW_TOPLEVEL);g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);gtk_window_set_title(GTK_WINDOW(window), "Spin Button");main_vbox = gtk_vbox_new(FALSE, 5);gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 10);gtk_container_add(GTK_CONTAINER(window), main_vbox);frame = gtk_frame_new("Not accelerated");gtk_box_pack_start(GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);vbox = gtk_vbox_new(FALSE, 0);gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);gtk_container_add(GTK_CONTAINER(frame), vbox);hbox = gtk_hbox_new(FALSE, 0);gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 5);vbox2 = gtk_vbox_new(FALSE, 0);gtk_box_pack_start(GTK_BOX(hbox), vbox2, TRUE, TRUE, 5);label = gtk_label_new("Day:");gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);gtk_box_pack_start(GTK_BOX(vbox2), label,FALSE, FALSE, 0);adj = (GtkAdjustment *)gtk_adjustment_new(1.0, 1.0, 31.0, 1.0, 5.0, 0.0);spinner = gtk_spin_button_new(adj, 0, 0);gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinner), TRUE);gtk_box_pack_start(GTK_BOX(vbox2), spinner, FALSE, TRUE, 0);vbox2 = gtk_vbox_new(FALSE, 0);gtk_box_pack_start(GTK_BOX(hbox), vbox2, TRUE, TRUE, 5);label = gtk_label_new("Month:");gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);gtk_box_pack_start(GTK_BOX(vbox2), label,FALSE, FALSE, 0);adj = (GtkAdjustment *)gtk_adjustment_new(1.0, 1.0, 12.0, 1.0, 5.0, 0.0);spinner = gtk_spin_button_new(adj, 0, 0);gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinner), TRUE);gtk_box_pack_start(GTK_BOX(vbox2), spinner, FALSE, TRUE, 0);vbox2 = gtk_vbox_new(FALSE, 0);gtk_box_pack_start(GTK_BOX(hbox), vbox2, TRUE, TRUE, 5);label = gtk_label_new("Year:");gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);gtk_box_pack_start(GTK_BOX(vbox2), label,FALSE, FALSE, 0);adj = (GtkAdjustment *)gtk_adjustment_new(1998.0, 0.0, 2100.0, 1.0, 100.0, 0.0);spinner = gtk_spin_button_new(adj, 0, 0);gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinner), TRUE);gtk_widget_set_size_request(spinner, 55, -1);gtk_box_pack_start(GTK_BOX(vbox2), spinner, FALSE, TRUE, 0);frame = gtk_frame_new("Accelerated");gtk_box_pack_start(GTK_BOX(main_vbox), frame, TRUE, TRUE, 0);vbox = gtk_vbox_new(FALSE, 0);gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);gtk_container_add(GTK_CONTAINER(frame), vbox);hbox = gtk_hbox_new(FALSE, 0);gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 5);vbox2 = gtk_vbox_new(FALSE, 0);gtk_box_pack_start(GTK_BOX(hbox), vbox2, TRUE, TRUE, 5);label = gtk_label_new("Value:");gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);gtk_box_pack_start(GTK_BOX(vbox2), label,FALSE, TRUE, 0);adj = (GtkAdjustment *)gtk_adjustment_new(0.0, -1000.0, 1000.0, 0.5, 100.0, 0.0);spinner1 = gtk_spin_button_new(adj, 1.0, 2);gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinner1), TRUE);gtk_widget_set_size_request(spinner, 100, -1);gtk_box_pack_start(GTK_BOX(vbox2), spinner1, FALSE, TRUE, 0);vbox2 = gtk_vbox_new(FALSE, 0);gtk_box_pack_start(GTK_BOX(hbox), vbox2, TRUE, TRUE, 5);label = gtk_label_new("Digits:");gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);gtk_box_pack_start(GTK_BOX(vbox2), label,FALSE, TRUE, 0);adj = (GtkAdjustment *)gtk_adjustment_new(2, 1, 5, 1, 1, 0);spinner2 = gtk_spin_button_new(adj, 0, 0);gtk_spin_button_set_wrap(GTK_SPIN_BUTTON(spinner2), TRUE);g_signal_connect(G_OBJECT(adj), "value_changed", G_CALLBACK(change_digits), (gpointer) spinner2);gtk_box_pack_start(GTK_BOX(vbox2), spinner2, FALSE, TRUE, 0);hbox = gtk_hbox_new(FALSE, 0);gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 5);button = gtk_check_button_new_with_label("Snap to 0.5-ticks");g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(toggle_snap), (gpointer)spinner1);gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);button = gtk_check_button_new_with_label("Numeric only input mode");g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(toggle_numeric), (gpointer)spinner1);gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);val_label = gtk_label_new("");hbox = gtk_hbox_new(FALSE, 0);gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 5);button = gtk_button_new_with_label("Value as Int");g_object_set_data(G_OBJECT(button), "user_data", val_label);g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(get_value), GINT_TO_POINTER(1));gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 5);button = gtk_button_new_with_label("Value as Float");g_object_set_data(G_OBJECT(button), "user_data", val_label);g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(get_value), GINT_TO_POINTER(2));gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 5);gtk_box_pack_start(GTK_BOX(vbox), val_label, TRUE, TRUE, 0);gtk_label_set_text(GTK_LABEL(val_label), "0");hbox = gtk_hbox_new(FALSE, 0);gtk_box_pack_start(GTK_BOX(main_vbox), hbox, FALSE, TRUE, 0);button = gtk_button_new_with_label("Close");g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(gtk_widget_destroy), G_OBJECT(window));gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 5);gtk_widget_show_all(window);gtk_main();return 0;}
编译命令:
gcc -Wall -g spinbutton.c -o spinbutton `pkg-config --cflags gtk+-2.0 pkg-config --libs gtk+-2.0`
Combo Box
Combox Box是一个widget的集合。它包含一个text entry box和一个下拉菜单。通过下拉菜单可以选择其中的项,也可以在text entry box中键入字符串。
下面举例说明。
程序运行结果:
/**combobox.c/#include<gtk/gtk.h>void on_combo_box_changed(GtkComboBox *combo_box, gpointer user_data)
{gint active_index = gtk_combo_box_get_active(combo_box);if(active_index != -1){GtkTreeModel *model;GtkTreeIter iter;gchar *item_text;model = gtk_combo_box_get_model(combo_box);gtk_tree_model_iter_nth_child(model, &iter, NULL, active_index);gtk_tree_model_get(model, &iter, 0, &item_text, -1);g_print("Selected item: %s\n", item_text);g_free(item_text);}
}int main(int argc, char *argv[])
{GtkWidget *window;GtkWidget *combo_box;GtkList *glist = NULL;GtkTreeIter iter;gtk_init(&argc, &argv);window = gtk_window_new(GTK_WINDOW_TOPLEVEL);gtk_window_set_title(GTK_WINDOW(window), "GTK ComboBox Example");gtk_window_set_default_size(GTK_WINDOW(window), 250, 150);g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);combo_box = gtk_combo_new();glist = g_list_append(glist, "String 1");glist = g_list_append(glist, "String 2");glist = g_list_append(glist, "String 3");glist = g_list_append(glist, "String 4");gtk_combo_set_popdown_strings(GTK_COMBO(combo_box), glist);g_signal_connect(combo_box, "changed", G_CALLBACK(on_combo_box_changed), NULL);gtk_container_add(GTK_CONTAINER(window), combo_box);gtk_widget_show_all(window);gtk_main();return 0;}
编译命令:
gcc -Wall -g combobox.c -o combobox `pkg-config --cflags gtk+-2.0 pkg-config --libs gtk+-2.0`
Calendar
如标题,这是一个用于显示日历的widget.下面我们举例说明其UI及其相关功能。
程序运行结果如下:
/*calendar.c*/
#include<stdio.h>
#include<string.h>
#include<gtk/gtk.h>#define DEF_PAD 10
#define DEF_PAD_SAMLL 5#define TM_YEAE_BASE 1900typedef struct _CalendarData{GtkWidget *flag_checkboxes[5];gboolean settings[5];GtkWidget *font_dialog;GtkWidget *window;GtkWidget *prev2_sig;GtkWidget *prev_sig;GtkWidget *last_sig;GtkWidget *month;
}CalendarData;enum{calendar_show_header,calendar_show_days,calendar_month_change,calendar_show_week,calendar_monday_first
};static void calendar_data_to_string(CalendarData *data, char *buffer,gint buffer_len)
{GDate date;guint year, month, day;gtk_calendar_get_date(GTK_CALENDAR(data->window), &year, &month, &day);g_date_set_dmy(&date, day, month + 1, year);g_date_strftime(buffer, buffer_len -1, "%x", &date);
}static void calendar_set_signal_strings(char *sig_str, CalendarData *data)
{const gchar *prev_sig;prev_sig = gtk_label_get_text(GTK_LABEL(data->prev2_sig));gtk_label_set_text(GTK_LABEL(data->prev2_sig), prev_sig);prev_sig = gtk_label_get_text(GTK_LABEL(data->last_sig));gtk_label_set_text(GTK_LABEL(data->prev_sig), prev_sig);gtk_label_set_text(GTK_LABEL(data->last_sig), sig_str);}static void calendar_month_changed(GtkWidget *widget, CalendarData *data)
{char buffer[256] = "month_changed: ";calendar_data_to_string(data, buffer + 15, 256 - 15);calendar_set_signal_strings(buffer, data);
}static void calendar_day_selected(GtkWidget *widget, CalendarData *data)
{char buffer[256] = "day_selected: ";calendar_data_to_string(data, buffer + 14, 256 - 14);calendar_set_signal_strings(buffer, data);
}static void calendar_day_selected_double_click(GtkWidget *widget, CalendarData *data)
{char buffer[256] = "day_selected_double_click: ";guint day;calendar_data_to_string(data, buffer + 27, 256 - 27);calendar_set_signal_strings(buffer, data);gtk_calendar_get_date(GTK_CALENDAR(data->window), NULL, NULL, &day);if(GTK_CALENDAR(data->window)->marked_date[day - 1] == 0)gtk_calendar_mark_day(GTK_CALENDAR(data->window), day);elsegtk_calendar_unmark_day(GTK_CALENDAR(data->window), day);
}static void calendar_prev_month(GtkWidget *widget, CalendarData *data)
{char buffer[256] = "prev_month: ";calendar_data_to_string(data, buffer + 12, 256 - 12);calendar_set_signal_strings(buffer, data);
}static void calendar_next_month(GtkWidget *widget, CalendarData *data)
{char buffer[256] = "next_month: ";calendar_data_to_string(data, buffer + 12, 256 - 12);calendar_set_signal_strings(buffer, data);
}static void calendar_prev_year(GtkWidget *widget, CalendarData *data)
{char buffer[256] = "prev_year: ";calendar_data_to_string(data, buffer + 11, 256 - 11);calendar_set_signal_strings(buffer, data);
}static void calendar_next_year(GtkWidget *widget, CalendarData *data)
{char buffer[256] = "next_year: ";calendar_data_to_string(data, buffer + 11, 256 - 11);calendar_set_signal_strings(buffer, data);
}static void calendar_set_flags(CalendarData *calendar)
{gint i;gint options = 0;for ( i = 0; i < 5; i++){if(calendar->settings[i])options = options + (1<<i); }if(calendar->window)gtk_calendar_display_options(GTK_CALENDAR(calendar->window), options);}static void calendar_toggle_flag(GtkWidget *toggle, CalendarData *calendar)
{gint i;gint j;j = 0;for ( i = 0; i < 5; i++){if(calendar->flag_checkboxes[i] == toggle)j = i;}calendar->settings[j] = !calendar->settings[j];calendar_set_flags(calendar);}static void calendar_font_selection_ok(GtkWidget *button, CalendarData *calendar)
{GtkRcStyle *style;char *font_name;if(calendar->window){font_name = gtk_font_selection_dialog_get_font_name(GTK_FONT_SELECTION_DIALOG(calendar->font_dialog));if(font_name){style = gtk_rc_style_new();pango_font_description_free(style->font_desc);style->font_desc = pango_font_description_from_string(font_name);gtk_widget_modify_style(calendar->window, style);g_free(font_name);}}gtk_widget_destroy(calendar->font_dialog);
}static void calendar_select_font(GtkWidget *button, CalendarData *calendar)
{GtkWidget *window;if(!calendar->font_dialog){window = gtk_font_selection_dialog_new("Font Selection Dialog");g_return_if_fail(GTK_IS_FONT_SELECTION_DIALOG(window));calendar->font_dialog = window;gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_MOUSE);g_signal_connect(window, "destroy",G_CALLBACK(gtk_widget_destroyed), &calendar->font_dialog);g_signal_connect(GTK_FONT_SELECTION_DIALOG(window)->ok_button, "clicked",G_CALLBACK(calendar_font_selection_ok), calendar);g_signal_connect_swapped(GTK_FONT_SELECTION_DIALOG(window)->cancel_button, "clicked",G_CALLBACK(gtk_widget_destroy), calendar->font_dialog);}window = calendar->font_dialog;if(!GTK_WIDGET_VISIBLE(window))gtk_widget_show(window);elsegtk_widget_destroy(window);
}static void create_calendar(void)
{GtkWidget *window;GtkWidget *vbox;GtkWidget *vbox2;GtkWidget *vbox3;GtkWidget *hbox;GtkWidget *hbbox;GtkWidget *calendar;GtkWidget *toggle;GtkWidget *button;GtkWidget *frame;GtkWidget *separator;GtkWidget *label;GtkWidget *bbox;static CalendarData calendar_data;gint i;struct {char *label;} flags[] ={{"Show Heading"},{"Show Day Names"},{"No Month Change"},{"Show Week Numbers"},{"Week Start Monday"}};calendar_data.window = NULL;calendar_data.font_dialog = NULL;for ( i = 0; i < 5; i++){calendar_data.settings[i] = 0;}window = gtk_window_new(GTK_WINDOW_TOPLEVEL);gtk_window_set_title(GTK_WINDOW(window), "GtkCalendar Example");gtk_container_set_border_width(GTK_CONTAINER(window), 5);g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);g_signal_connect(window, "delete-event", G_CALLBACK(gtk_false), NULL);gtk_window_set_resizable(GTK_WINDOW(window), FALSE);vbox = gtk_vbox_new(FALSE, DEF_PAD);gtk_container_add(GTK_CONTAINER(window), vbox);hbox = gtk_hbox_new(FALSE, DEF_PAD);gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, DEF_PAD);hbbox = gtk_hbutton_box_new();gtk_box_pack_start(GTK_BOX(hbox), hbbox, FALSE, FALSE, DEF_PAD);gtk_button_box_set_layout(GTK_BUTTON_BOX(hbbox), GTK_BUTTONBOX_SPREAD);gtk_box_set_spacing(GTK_BOX(hbbox), 5);frame = gtk_frame_new("calendar");gtk_box_pack_start(GTK_BOX(hbbox), frame, FALSE, TRUE, DEF_PAD);calendar = gtk_calendar_new();calendar_data.window = calendar;calendar_set_flags(&calendar_data);gtk_calendar_mark_day(GTK_CALENDAR(calendar), 19);gtk_container_add(GTK_CONTAINER(frame), calendar);g_signal_connect(calendar, "month_changed", G_CALLBACK(calendar_month_changed), &calendar_data);g_signal_connect(calendar, "day_selected", G_CALLBACK(calendar_day_selected), &calendar_data);g_signal_connect(calendar, "day_selected_double_click", G_CALLBACK(calendar_day_selected_double_click), &calendar_data);g_signal_connect(calendar, "prev_month", G_CALLBACK(calendar_prev_month), &calendar_data);g_signal_connect(calendar, "next_month", G_CALLBACK(calendar_next_month), &calendar_data);g_signal_connect(calendar, "prev_year", G_CALLBACK(calendar_prev_year), &calendar_data);g_signal_connect(calendar, "next_year", G_CALLBACK(calendar_next_year), &calendar_data);separator = gtk_vseparator_new();gtk_box_pack_start(GTK_BOX(hbox), separator, FALSE, TRUE, 0);vbox2 = gtk_vbox_new(FALSE, DEF_PAD);gtk_box_pack_start(GTK_BOX(hbox), vbox2, FALSE, FALSE, DEF_PAD);frame = gtk_frame_new("flags");gtk_box_pack_start(GTK_BOX(vbox2), frame, TRUE, TRUE, DEF_PAD);vbox3 = gtk_vbox_new(TRUE, DEF_PAD_SAMLL);gtk_container_add(GTK_CONTAINER(frame), vbox3);for ( i = 0; i < 5; i++){toggle = gtk_check_button_new_with_label(flags[i].label);g_signal_connect(toggle, "toggled", G_CALLBACK(calendar_toggle_flag), &calendar_data);gtk_box_pack_start(GTK_BOX(vbox3), toggle, TRUE, TRUE, 0);calendar_data.flag_checkboxes[i] = toggle;}button = gtk_button_new_with_label("Font...");g_signal_connect(button, "clicked",G_CALLBACK(calendar_select_font), &calendar_data);gtk_box_pack_start(GTK_BOX(vbox2), button, FALSE, FALSE, 0);frame = gtk_frame_new("Signal events");gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, DEF_PAD);vbox2 = gtk_vbox_new(TRUE, DEF_PAD_SAMLL);gtk_container_add(GTK_CONTAINER(frame), vbox2);hbox = gtk_hbox_new(FALSE, 3);gtk_box_pack_start(GTK_BOX(vbox2), hbox, FALSE, TRUE, 0);label = gtk_label_new("Signal:");gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 0);calendar_data.last_sig = gtk_label_new("");gtk_box_pack_start(GTK_BOX(hbox), calendar_data.last_sig, FALSE, TRUE, 0);hbox = gtk_hbox_new(FALSE, 3);gtk_box_pack_start(GTK_BOX(vbox2), hbox, FALSE, TRUE, 0);label = gtk_label_new("Previous signal:");gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 0);calendar_data.prev_sig = gtk_label_new("");gtk_box_pack_start(GTK_BOX(hbox), calendar_data.prev_sig, FALSE, TRUE, 0);hbox = gtk_hbox_new(FALSE, 3);gtk_box_pack_start(GTK_BOX(vbox2), hbox, FALSE, TRUE, 0);label = gtk_label_new("Second previous signal:");gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 0);calendar_data.prev2_sig = gtk_label_new("");gtk_box_pack_start(GTK_BOX(hbox), calendar_data.prev2_sig, FALSE, TRUE, 0);bbox = gtk_hbutton_box_new();gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);button = gtk_button_new_with_label("close");g_signal_connect(button, "clicked",G_CALLBACK(gtk_main_quit), NULL);gtk_container_add(GTK_CONTAINER(bbox), button);GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);gtk_widget_grab_default(button);gtk_widget_show_all(window);}int main(int argc, char *argv[])
{gtk_init(&argc, &argv);create_calendar();gtk_main();return 0;
}
编译命令:
gcc -Wall -g calendar.c -o calendar `pkg-config --cflags gtk+-2.0 pkg-config --libs gtk+-2.0`