GTK构件之微调按钮

时间:2022-11-04 15:16:18

GTK构件之微调按钮

1.微调按钮简介

       微调按钮(Spin Button)构件通常用于让用户从一个取值范围你选择一个值。它由一个文本输入框和旁边的向上和向下两个按钮组成。点击某一个按钮会让文本输入框里的数值大小在一定范围你改变。文本输入框里也可以直接输入一个特定值。

       微调按钮构件允许其中的数值没有小数位或具有指定的小数位,并且数值可以按一种可配置的方式增加或减小。在按钮较长时间呈按下状态时,构件的数值会根据工具按下时间的长短加速变化。

       微调按钮用一个调整对象来维护该按钮能够取值的范围。微调按钮构件因此而具有了很强大的功能。

2.调整对象简介

     GTK 有多种构件能够由用户通过鼠标或键盘进行调整,比如范围构件。还有一些构件,比如说 GtkText 和GtkViewport,内部都有一些可调整的属性。

       很明显,当用户调整范围构件的值时,应用程序需要对值的变化进行响应。一种办法就是当构件的调整值发生变化时,让每个构件引发自己的信号,将新值传递到信号处理函数中,或者让它在构件的内部数据结构中查找构件的值。 但是,也许需要将这个调整值同时连接到几个构件上,使得调整一个值时,其它的构件都随之响应。最明显的示例就是将一个滚动条连接到一个视角构件(viewport)或者滚动的文本区(text area)上。如果每个构件都要有自己的设置或获取调整值的方法,程序员或许需要自己编写很复杂的信号处理函数,以便将这些不同构件之间的变化同步或相关联。

       GTK用一个调整对象(Adjustment object)解决了这个问题。调整对象不是构件,但是为构件提供了一种以抽象、 灵活的方法来传递调整值信息。调整对象最明显的用处就是为范围构件(比如滚动条和比例构件)储存配置参数和值。 然而,因为调整对象是从 Object派生的,在其正常的数据结构之外,它还具有一些特殊的功能。 最重要的是,它们能 够引发信号,就像构件一样,这些信号不仅能够让程序对用户在可调整构件上的输入进行响应,还能在可调整构件之间透明地传播调整值。

       在许多其它的构件中都能够看到调整对象的用处。比如进度条、 视角 、 滚动窗口等。

  •  微调按钮中创建调整对象函数:
GtkAdjustment *gtk_adjustment_new (gdouble value,
gdouble lower,gdouble upper,
gdouble step_increment,gdouble page_increment,
gdouble page_size);
形参:value -- 微调按钮初始值
lower、upper --构件允许的最大值、最小值
step_increment --鼠标左键按下构件一次增加/减小的值
page_increment --鼠标右键下构件一次增加/减少的值
page_size --没有用到
返回值:返回微调按钮构件对象
  •  微调按钮创建函数:
GtkWidget *gtk_spin_button_new (GtkAdjustment *adjustment,gdouble  climb_rate,guint digits)
形参:adjustment --调整对象
climb_rate --指明构件数值变化的加速度(长时间按住按钮, 数值会加速变化)。介于0.0~1.0之间
digits --微调按就值小数位数
  •  微调按钮参数配置函数:
void gtk_spin_button_configure( GtkSpinButton *spin_button,GtkAdjustment *adjustment,
gdouble climb_rate,guint digits );
形参:spin_button --微调按钮控件
adjustment --调整对象
climb_rate --指明构件数值变化的加速度(长时间按住按钮, 数值会加速变化)。介于0.0~1.0之间
digits --微调按就值小数位数
  •  设置或获取构件内部使用的调整对象:
/*获取微调按钮调整对象信息*/
GtkAdjustment *gtk_spin_button_get_adjustment (GtkSpinButton *spin_button);
/*设置微调按钮调整对象信息*/
gtk_spin_button_set_adjustment (GtkSpinButton *spin_button,GtkAdjustment *adjustment);
  •  设置微调按钮小数位数:
void gtk_spin_button_set_digits (GtkSpinButton *spin_button,guint digits)
形参:spin_button --微调按钮控件
digits --微调按钮数值小数位数
  •  设置微调按钮数值:
void gtk_spin_button_set_value (GtkSpinButton *spin_button,gdouble value);
形参:spin_button --微调按钮控件
value-- 要设置的数值
  •  获取按钮当前数值:
/*以整数方式获取当前按钮数值*/
gdouble gtk_spin_button_get_value ( GtkSpinButton *spin_button );
/*以小数方式获取当前按钮数值*/
gint gtk_spin_button_get_value_as_int( GtkSpinButton *spin_button );
  •  以当前值为基准修改微调按钮数值:
void gtk_spin_button_spin( GtkSpinButton *spin_button,GtkSpinType direction,gdouble increment );
形参:spin_button --微调按钮控件
direction 取以下参数:
GTK_SPIN_STEP_FORWARD
GTK_SPIN_STEP_BACKWARD
GTK_SPIN_PAGE_FORWARD
GTK_SPIN_PAGE_BACKWARD
GTK_SPIN_HOME
GTK_SPIN_END
GTK_SPIN_USER_DEFINED

  GTK_SPIN_STEP_FORWARDGTK_SPIN_STEP_BACKWARD将构件的值按increment参数指定的数值增大或减小,除非increment参数是 0。这种情况下,构件的值将按与其相关联的调整对象的step_increment值改变。

 GTK_SPIN_PAGE_FORWARDGTK_SPIN_PAGE_BACKWARD只是简单地按increment参数改变微调按钮构件的值。

 GTK_SPIN_HOME 将构件的值设置为相关联调整对象的范围的最小值。

 GTK_SPIN_END 将构件的值设置为相关联调整对象的范围的最大值。

 GTK_SPIN_USER_DEFINED简单地按指定的数值改变构件的数值。


  •  限制微调按钮构件的文本框只能输入数值:
void gtk_spin_button_set_numeric (GtkSpinButton *spin_button,gboolean numeric)
形参:spin_button --微调按钮控件
numeric --TRUE 只能输入数字;FALSE 可以输入任意内容
  •  设置让微调按钮构件在upper和lower之间循环:
void gtk_spin_button_set_wrap (GtkSpinButton  *spin_button, gboolean wrap)
形参:spin_button --微调按钮控件
wrap --TRUE 当按钮值到达最小值再往下调整将变为最大值;最大值再往上调整将为最小值
FALSE 当按钮值到达最小值再往下调整将保持不变;最大值再往上调整保持不变

  可以设置让微调按钮构件将其值圆整到最接近 step_increment 的值(在该微调按钮构件使用的调整对象中设置的)。用下面的函数实现:

void gtk_spin_button_set_snap_to_ticks( GtkSpinButton *spin_button,gboolean snap_to_ticks );
  •  微调按钮构件的更新方式可以用下面的函数改变:
void gtk_spin_button_set_update_policy( GtkSpinButton*spin_button,GtkSpinButtonUpdatePolicy policy );
形参:spin_button --微调按钮控件
policy --可以取如下值:
GTK_UPDATE_ALWAYS
GTK_UPDATE_IF_VALID。

  在GTK_UPDATE_IF_VALID方式下,微调按钮构件只有在输入文本是其调整对象指定范围你合法的值时才进行更新,否则文本会被重置为当前的值。

  在GTK_UPDATE_ALWAYS方式下,我们将忽略在文本转换为数值时的错误。

  •  更新微调按钮:
void gtk_spin_button_update( GtkSpinButton *spin_button );

3.微调按钮示例

GTK构件之微调按钮

  • 本示例实现共能如下:
  1. 通过微调按钮数值日期(年、月、日);
  2. 通过复选按钮选择微调按钮仅能输入数字;
  3. 设置数值的小数位数
  4. 退出按钮通过对话框提示是否退出,保存按钮提示保存成功;
#include <gtk/gtk.h>
#include <stdio.h>
/*微调按钮回调函数*/
void spin_button_callback(GtkWidget *widget,gpointer data)
{
GtkWidget *spinbutton=(GtkWidget *)data;
int val;
/*获取当前微调按钮的值*/
val=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget));
g_print("val=%d\n",val);
/*修改小数位数*/
gtk_spin_button_set_digits(GTK_SPIN_BUTTON(spinbutton),val);
}
/*复选按钮处理函数*/
void check_button_callback(GtkWidget *widget,gpointer data)
{
GtkWidget *spinbutton=(GtkWidget *)data;
if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
{
/*设置微调按钮只能输入数字*/
gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spinbutton),TRUE);
}
else
{
/*设置微调按钮可以输入任意内容*/
gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spinbutton),FALSE);
}
}
/*保存按钮处理函数*/
void save_button_callback(GtkWidget *widget,gpointer data)
{
g_print("保存\n");
GtkWidget *window=(GtkWidget *)data;
GtkWidget *dialog;
GtkWidget *label;
dialog=gtk_dialog_new_with_buttons("保存", GTK_WINDOW(window),GTK_DIALOG_MODAL,NULL);
gtk_window_set_default_size(GTK_WINDOW(dialog),100, 100);
label=gtk_label_new("保存成功\n");
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),label,TRUE, TRUE,0);
gtk_widget_show(label);
gtk_widget_show(dialog);
}
GtkWidget *dialog;
/*对话框处理回调函数*/
void button_clicked_callback(GtkWidget *widget,gpointer data)
{
char *pada=(gchar *)data;
if(!strcmp(pada,"on"))
{
gtk_widget_destroy(dialog);//关闭对话框
}
if(!strcmp(pada,"ok"))
{
gtk_main_quit();
}
}
/*退出按钮处理函数*/
void quit_button_callback(GtkWidget *widget,gpointer data)
{
g_print("退出\n");
GtkWidget *window=(GtkWidget *)data;
GtkWidget *label;
GtkWidget *table;
GtkWidget *button;
dialog=gtk_dialog_new_with_buttons("是否退出", GTK_WINDOW(window),GTK_DIALOG_MODAL,NULL);
gtk_window_set_default_size(GTK_WINDOW(dialog),100, 100);
label=gtk_label_new("是否退出");
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),label,TRUE, TRUE,0);
gtk_widget_show(label);

/*创建组装表*/
table=gtk_table_new(1,0,FALSE);
gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),table,FALSE, FALSE, 0);
gtk_widget_show(table);
/*创建按钮*/
button=gtk_button_new_from_stock(GTK_STOCK_NO);
gtk_table_attach_defaults(GTK_TABLE(table),button,0,1,0,1);
gtk_widget_show(button);
g_signal_connect(GTK_OBJECT(button),"clicked",G_CALLBACK(button_clicked_callback),"on");
/*创建按钮*/
button=gtk_button_new_from_stock(GTK_STOCK_OK);
gtk_table_attach_defaults(GTK_TABLE(table),button,1,2,0,1);
g_signal_connect(GTK_OBJECT(button),"clicked",G_CALLBACK(button_clicked_callback),"ok");
gtk_widget_show(button);
gtk_widget_show(dialog);
}
int main(int argc,char *argv[])
{
GtkWidget *window;
GtkWidget *vbox,*box;
GtkWidget *frame;
GtkAdjustment *adjust;
GtkWidget *table;
GtkWidget *label;
GtkWidget *spin_button,*spin_val_button;
GtkWidget *check_button;
GtkWidget *button;
gtk_init(&argc,&argv);
window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "微调按钮");
gtk_window_set_default_size(GTK_WINDOW(window),320, 240);
gtk_container_set_border_width(GTK_CONTAINER(window) ,5);
g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(gtk_main_quit),NULL);

/*创建纵向盒*/
vbox=gtk_vbox_new(FALSE,0);
gtk_container_set_border_width(GTK_CONTAINER(vbox) ,2);
gtk_container_add(GTK_CONTAINER(window),vbox);
gtk_widget_show(vbox);
/*创建框架构件*/
frame=gtk_frame_new("日期设置");
gtk_frame_set_label_align(GTK_FRAME(frame),1.0,0.5);
/*设置框架构件风格*/
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_OUT);
gtk_box_pack_start(GTK_BOX(vbox),frame, FALSE,TRUE,0);
gtk_widget_show(frame);

/*创建组装表*/
table=gtk_table_new(2,3,FALSE);
gtk_container_add(GTK_CONTAINER(frame),table);
/*设置列之间的间隔*/
gtk_table_set_col_spacings(GTK_TABLE(table),20);
gtk_widget_show(table);

/*创建调整对象*/
adjust=(GtkAdjustment *)gtk_adjustment_new(2022,1970,3000,1,1,0);
/*创建微调按钮*/
spin_button=gtk_spin_button_new(adjust,0.5, 0);
/*限制微调按钮只能输入数值*/
gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spin_button),TRUE);
/*设置按钮达到最大值后再变为最小值*/
gtk_spin_button_set_wrap (GTK_SPIN_BUTTON(spin_button), TRUE);
gtk_table_attach_defaults (GTK_TABLE(table),spin_button,0,1,1,2);
gtk_widget_show(spin_button);
/*设置标签*/
label=gtk_label_new("年");
gtk_table_attach_defaults(GTK_TABLE(table),label,0,1,0,1);

gtk_widget_show(label);

/*创建微调按钮*/
adjust=(GtkAdjustment *)gtk_adjustment_new(1,1,12,1,1,0);
spin_button=gtk_spin_button_new(adjust,1, 0);
gtk_spin_button_set_wrap (GTK_SPIN_BUTTON(spin_button), TRUE);
gtk_table_attach_defaults (GTK_TABLE(table),spin_button,1,2,1,2);
gtk_widget_show(spin_button);
/*设置标签*/
label=gtk_label_new("月");
gtk_table_attach_defaults(GTK_TABLE(table),label,1,2,0,1);
gtk_widget_show(label);

/*创建微调按钮*/
adjust=(GtkAdjustment *)gtk_adjustment_new(1,1,31,1,1,0);
spin_button=gtk_spin_button_new(adjust,0.5, 0);
gtk_spin_button_set_wrap (GTK_SPIN_BUTTON(spin_button), TRUE);
gtk_table_attach_defaults (GTK_TABLE(table),spin_button,2,3,1,2);
gtk_widget_show(spin_button);
/*设置标签*/
label=gtk_label_new("日");
gtk_table_attach_defaults(GTK_TABLE(table),label,2,3,0,1);
gtk_widget_show(label);

/*创建框架构件*/
frame=gtk_frame_new("数值调整");
gtk_frame_set_label_align(GTK_FRAME(frame),0.5,0.5);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_OUT);
gtk_box_pack_start(GTK_BOX(vbox),frame, FALSE,TRUE,0);
gtk_widget_show(frame);
/*创建纵向向盒*/
box=gtk_vbox_new(FALSE,0);
gtk_container_add(GTK_CONTAINER(frame),box);
gtk_widget_show(box);
/*创建组装表*/
table=gtk_table_new(2,2,FALSE);
gtk_box_pack_start(GTK_BOX(box),table,TRUE,TRUE,0);
/*设置列之间的间隔*/
gtk_table_set_col_spacings(GTK_TABLE(table),10);
gtk_widget_show(table);
/*创建调整对象*/
adjust=(GtkAdjustment *)gtk_adjustment_new(0,-5000,5000,0.5,0.5,0);
spin_val_button=gtk_spin_button_new(adjust,0.5, 2);
gtk_table_attach_defaults (GTK_TABLE(table),spin_val_button,0,1,1,2);
gtk_widget_show(spin_val_button);
/*设置标签*/
label=gtk_label_new("数值");
gtk_table_attach_defaults(GTK_TABLE(table),label,0,1,0,1);
gtk_widget_show(label);

/*创建调整对象*/
adjust=(GtkAdjustment *)gtk_adjustment_new(2,0,6,1,1,0);
spin_button=gtk_spin_button_new(adjust,0.5, 0);
g_signal_connect(G_OBJECT(spin_button),"value_changed",G_CALLBACK(spin_button_callback), spin_val_button);
gtk_table_attach_defaults (GTK_TABLE(table),spin_button,1,2,1,2);
gtk_widget_show(spin_button);
/*设置标签*/
label=gtk_label_new("小数位数");
gtk_table_attach_defaults(GTK_TABLE(table),label,1,2,0,1);
gtk_widget_show(label);

/*创建复选按钮*/
check_button=gtk_check_button_new_with_label("仅输入数字");
gtk_box_pack_start(GTK_BOX(box),check_button,FALSE,FALSE,0);
g_signal_connect(G_OBJECT(check_button),"toggled",G_CALLBACK(check_button_callback), spin_button);
gtk_widget_show(check_button);

/*创建横向盒*/
box=gtk_hbox_new(FALSE,0);
gtk_box_pack_start(GTK_BOX(vbox),box,TRUE,TRUE,0);
gtk_widget_show(box);

/*创建保存按钮*/
button=gtk_button_new_with_label("退出");
gtk_box_pack_start(GTK_BOX(box),button,FALSE,FALSE,0);
g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(quit_button_callback),window);
gtk_widget_show(button);

/*创建保存按钮*/
button=gtk_button_new_with_label("保存");
gtk_box_pack_end(GTK_BOX(box),button,FALSE,FALSE,0);
g_signal_connect(G_OBJECT(button),"clicked",G_CALLBACK(save_button_callback),window);
gtk_widget_show(button);
gtk_widget_show(window);
gtk_main();
}