微调按钮(SpinButton)
SpinButton允许用户从一个数值范围内选择一个值。它包含了一个Entry部件在其侧边有递增和递减按钮。单击按钮会使得值在可能的范围内“旋转”。你也可以直接在Entry部件中输入一个值。
这个值的小数位可以进行调整,步长也可以进行配置。SpinButton具有“自动重复”功能:长按递增、递减按钮该值的变化速度会越来越快。
SpinButton使用调整(Adjustment)对象保存值的范围信息。下述调整属性由微调按钮使用:
- value:微调按钮的值
- lower:微调按钮允许的最小值
- upper:微调按钮允许的最大值
- step_increment:鼠标键1(通常是左键)点击一下递增/递减的值
- page_increment:鼠标键2(通常是右键)点击一下递增/递减的值
- page_size:目前没作用
另外,鼠标键3(通常是中键)用于直接跳到upper或lower values。
SpinButton可以创建一个默认状态的Adjustment,然后你可以调用get_adjustment()方法访问这个Adjustment,也可以通过SpinButton的构造函数直接使用一个已经存在的Adjustment。
8.3.1. 方法
数值的小数位可以使用set_digits()方法进行调整。
你可以使用set_value()方法设置微调按钮的值,也可以使用get_value()方法获得微调按钮的值。
spin()方法的行为和手动点击递增/递减按钮一样。你需要传递一个Gtk::SpinType对象给该方法以指定是递增还是递减。
将true传递给set_numeric()方法可以阻止用户在条目框内输入非数字字符。
使用set_wrap()方法指定SpinButton的值到达上下限的时候是否绕回。
使用set_snap_to_ticks()方法可以在向微调按钮设置了无效值的时候强制校正到最接近step_increment策略可达到的有效值。
8.3.2. 示例
这是一个使用SpinButton的示例:
File: examplewindow.h (For use with gtkmm 4)
#ifndef GTKMM_EXAMPLEWINDOW_H #define GTKMM_EXAMPLEWINDOW_H #include <gtkmm.h> class ExampleWindow : public Gtk::Window { public: ExampleWindow(); virtual ~ExampleWindow(); protected: //Signal handlers: void on_checkbutton_snap(); void on_checkbutton_numeric(); void on_spinbutton_digits_changed(); void on_button_close(); enum enumValueFormats { VALUE_FORMAT_INT, VALUE_FORMAT_FLOAT }; void on_button_getvalue(enumValueFormats display); //Child widgets: Gtk::Frame m_Frame_NotAccelerated, m_Frame_Accelerated; Gtk::Box m_HBox_NotAccelerated, m_HBox_Accelerated, m_HBox_Buttons; Gtk::Box m_VBox_Main, m_VBox, m_VBox_Day, m_VBox_Month, m_VBox_Year, m_VBox_Accelerated, m_VBox_Value, m_VBox_Digits; Gtk::Label m_Label_Day, m_Label_Month, m_Label_Year, m_Label_Value, m_Label_Digits, m_Label_ShowValue; Glib::RefPtr<Gtk::Adjustment> m_adjustment_day, m_adjustment_month, m_adjustment_year, m_adjustment_value, m_adjustment_digits; Gtk::SpinButton m_SpinButton_Day, m_SpinButton_Month, m_SpinButton_Year, m_SpinButton_Value, m_SpinButton_Digits; Gtk::CheckButton m_CheckButton_Snap, m_CheckButton_Numeric; Gtk::Button m_Button_Int, m_Button_Float, m_Button_Close; }; #endif //GTKMM_EXAMPLEWINDOW_H
File: main.cc (For use with gtkmm 4)
#include "examplewindow.h" #include <gtkmm/application.h> int main(int argc, char *argv[]) { auto app = Gtk::Application::create("org.gtkmm.example"); //Shows the window and returns when it is closed. return app->make_window_and_run<ExampleWindow>(argc, argv); }
File: examplewindow.cc (For use with gtkmm 4)
#include "examplewindow.h" #include <iostream> #include <cstdio> ExampleWindow::ExampleWindow() : m_Frame_NotAccelerated("Not accelerated"), m_Frame_Accelerated("Accelerated"), m_VBox_Main(Gtk::Orientation::VERTICAL, 5), m_VBox(Gtk::Orientation::VERTICAL), m_VBox_Day(Gtk::Orientation::VERTICAL), m_VBox_Month(Gtk::Orientation::VERTICAL), m_VBox_Year(Gtk::Orientation::VERTICAL), m_VBox_Accelerated(Gtk::Orientation::VERTICAL), m_VBox_Value(Gtk::Orientation::VERTICAL), m_VBox_Digits(Gtk::Orientation::VERTICAL), m_Label_Day("Day: ", Gtk::Align::START), m_Label_Month("Month: ", Gtk::Align::START), m_Label_Year("Year: ", Gtk::Align::START), m_Label_Value("Value: ", Gtk::Align::START), m_Label_Digits("Digits: ", Gtk::Align::START), m_adjustment_day( Gtk::Adjustment::create(1.0, 1.0, 31.0, 1.0, 5.0, 0.0) ), m_adjustment_month( Gtk::Adjustment::create(1.0, 1.0, 12.0, 1.0, 5.0, 0.0) ), m_adjustment_year( Gtk::Adjustment::create(2012.0, 1.0, 2200.0, 1.0, 100.0, 0.0) ), m_adjustment_value( Gtk::Adjustment::create(0.0, -10000.0, 10000.0, 0.5, 100.0, 0.0) ), m_adjustment_digits( Gtk::Adjustment::create(2.0, 1.0, 5.0, 1.0, 1.0, 0.0) ), m_SpinButton_Day(m_adjustment_day), m_SpinButton_Month(m_adjustment_month), m_SpinButton_Year(m_adjustment_year), m_SpinButton_Value(m_adjustment_value, 1.0, 2), m_SpinButton_Digits(m_adjustment_digits), m_CheckButton_Snap("Snap to 0.5-ticks"), m_CheckButton_Numeric("Numeric only input mode"), m_Button_Int("Value as Int"), m_Button_Float("Value as Float"), m_Button_Close("Close") { set_title("SpinButton"); m_VBox_Main.set_margin(10); set_child(m_VBox_Main); m_VBox_Main.append(m_Frame_NotAccelerated); m_VBox.set_margin(5); m_Frame_NotAccelerated.set_child(m_VBox); /* Day, month, year spinners */ m_VBox.set_spacing(5); m_VBox.append(m_HBox_NotAccelerated); m_Label_Day.set_expand(); m_VBox_Day.append(m_Label_Day); m_SpinButton_Day.set_wrap(); m_SpinButton_Day.set_expand(); m_VBox_Day.append(m_SpinButton_Day); m_HBox_NotAccelerated.set_spacing(5); m_HBox_NotAccelerated.append(m_VBox_Day); m_Label_Month.set_expand(); m_VBox_Month.append(m_Label_Month); m_SpinButton_Month.set_wrap(); m_SpinButton_Month.set_expand(); m_VBox_Month.append(m_SpinButton_Month); m_HBox_NotAccelerated.append(m_VBox_Month); m_Label_Year.set_expand(); m_VBox_Year.append(m_Label_Year); m_SpinButton_Year.set_wrap(); m_SpinButton_Year.set_expand(); m_SpinButton_Year.set_size_request(55, -1); m_VBox_Year.append(m_SpinButton_Year); m_HBox_NotAccelerated.append(m_VBox_Year); //Accelerated: m_VBox_Main.append(m_Frame_Accelerated); m_VBox_Accelerated.set_margin(5); m_Frame_Accelerated.set_child(m_VBox_Accelerated); m_VBox_Accelerated.set_spacing(5); m_VBox_Accelerated.append(m_HBox_Accelerated); m_HBox_Accelerated.append(m_VBox_Value); m_Label_Value.set_expand(); m_VBox_Value.append(m_Label_Value); m_SpinButton_Value.set_wrap(); m_SpinButton_Value.set_expand(); m_SpinButton_Value.set_size_request(100, -1); m_VBox_Value.append(m_SpinButton_Value); m_HBox_Accelerated.append(m_VBox_Digits); m_VBox_Digits.append(m_Label_Digits); m_Label_Digits.set_expand(); m_SpinButton_Digits.set_wrap(); m_adjustment_digits->signal_value_changed().connect( sigc::mem_fun(*this, &ExampleWindow::on_spinbutton_digits_changed) ); m_VBox_Digits.append(m_SpinButton_Digits); m_SpinButton_Digits.set_expand(); //CheckButtons: m_VBox_Accelerated.append(m_CheckButton_Snap); m_CheckButton_Snap.set_expand(); m_CheckButton_Snap.set_active(); m_CheckButton_Snap.signal_toggled().connect( sigc::mem_fun(*this, &ExampleWindow::on_checkbutton_snap) ); m_VBox_Accelerated.append(m_CheckButton_Numeric); m_CheckButton_Numeric.set_expand(); m_CheckButton_Numeric.set_active(); m_CheckButton_Numeric.signal_toggled().connect( sigc::mem_fun(*this, &ExampleWindow::on_checkbutton_numeric) ); //Buttons: m_VBox_Accelerated.append(m_HBox_Buttons); m_Button_Int.signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ExampleWindow::on_button_getvalue), VALUE_FORMAT_INT) ); m_HBox_Buttons.set_spacing(5); m_HBox_Buttons.append(m_Button_Int); m_Button_Int.set_expand(); m_Button_Float.signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ExampleWindow::on_button_getvalue), VALUE_FORMAT_FLOAT) ); m_HBox_Buttons.append(m_Button_Float); m_Button_Float.set_expand(); m_VBox_Accelerated.append(m_Label_ShowValue); m_Label_ShowValue.set_expand(); m_Label_ShowValue.set_text("0"); //Close button: m_Button_Close.signal_clicked().connect( sigc::mem_fun(*this, &ExampleWindow::on_button_close) ); m_VBox_Main.append(m_Button_Close); } ExampleWindow::~ExampleWindow() { } void ExampleWindow::on_button_close() { hide(); } void ExampleWindow::on_checkbutton_snap() { m_SpinButton_Value.set_snap_to_ticks( m_CheckButton_Snap.get_active() ); } void ExampleWindow::on_checkbutton_numeric() { m_SpinButton_Value.set_numeric( m_CheckButton_Numeric.get_active() ); } void ExampleWindow::on_spinbutton_digits_changed() { m_SpinButton_Value.set_digits( m_SpinButton_Digits.get_value_as_int() ); } void ExampleWindow::on_button_getvalue(enumValueFormats display) { gchar buf[32]; if (display == VALUE_FORMAT_INT) sprintf (buf, "%d", m_SpinButton_Value.get_value_as_int()); else sprintf (buf, "%0.*f", m_SpinButton_Value.get_digits(), m_SpinButton_Value.get_value()); m_Label_ShowValue.set_text(buf); }