Chapter 9. コンボボックス

Table of Contents

ComboBoxComboBoxEntryウィジットはリスト(またはツリー)からドロップダウンメニューで選択する機能を提供します。適切に設定すれば、アイテムごとに追加の情報として、テキストやイメージ、チェックボックス、プログレスバーを表示することができます。ComboxBoxウィジットはユーザーの選択を利用可能なものに制限していますが、ComboBoxEntryEntryを持っているので、適当な選択肢がなかった場合、ユーザーは任意のテキストを入力することができます。

両方のウィジットでリストはTreeModel経由で提供されます。モデルの列をコンボボックスのビューにComboBox::pack_start()で追加します。こうすることは大変な柔軟性とコンパイル時の型安全性をもたらします。しかし、ComboBoxTextComboBoxEntryTextクラスでは柔軟性が必要でないならば単純なテキストベースの特殊クラスを提供します。

コンボボックス

Reference

モデル

ComboBoxのモデルはTreeViewのそれと全く同様に定義され、データを入れることができます。例えば、ComboBoxクラスを派生して、整数とテキストをひとつづつ持つようにするとこのようになります:

ModelColumns()
{ add(m_col_id); add(m_col_name); }

  Gtk::TreeModelColumn<int> m_col_id;
  Gtk::TreeModelColumn<Glib::ustring> m_col_name;
};

ModelColumns m_columns;

このモデルに行を加えた後、モデルをComboBoxset_model()メソッドで与えます。そして、pack_start()pack_end()メソッドを使ってどのデータがコンボボックスに表示されるか指定します。ツリービューのときと同様に、TreeModelColumnをパックメソッドに渡してデフォルトのセルレンダラを使うこともできますし、特定のCellRendererをインスタンス化してadd_attribute()set_cell_data_func()を使うことで特別なマッピングを指定することもできます。これらのメソッドはCellLayout基底クラスにあるということに注意してください。

選択したアイテム

コンボボックスでユーザーがどのアイテムを(いくつ)選択したのか調べるには、ComboBox::get_active()を使ってください。これはTreeModel::iteratorを返しますから、Rowに逆参照して列の値を読むことができます。例えば、コンボボックスから選んだモデルの整数のID値を得て、わかりやすい説明文を見せるということもできます:

Gtk::TreeModel::iterator iter = m_Combo.get_active();
if(iter)
{
  Gtk::TreeModel::Row row = *iter;

  //Get the data for the selected row, using our knowledge
  //of the tree model:
  int id = row[m_Columns.m_col_id];
  set_something_id_chosen(id); //Your own function.
}
else
  set_nothing_chosen(); //Your own function.

変化に対応する

コンボボックスの選択を変更することで、例えば、別のウィジットをアップデートするように反応させたいと思う場合があるかもしれません。これを行なうには、"chagnged"シグナルをハンドルしなければいけません。例えば:

m_combo.signal_changed().connect( sigc::mem_fun(*this,
      &ExampleWindow::on_combo_changed) );

Full Example

Figure 9.1. ComboBox

ComboBox

Source Code

File: examplewindow.h

#ifndef GTKMM_EXAMPLEWINDOW_H
#define GTKMM_EXAMPLEWINDOW_H

#include <gtkmm/window.h>
#include <gtkmm/comboboxtext.h>
#include <gtkmm/liststore.h>

class ExampleWindow : public Gtk::Window
{
public:
  ExampleWindow();
  virtual ~ExampleWindow();

protected:  
  //Signal handlers:
  virtual void on_combo_changed();

  //Tree model columns:
  class ModelColumns : public Gtk::TreeModel::ColumnRecord
  {
  public:

    ModelColumns()
    { add(m_col_id); add(m_col_name); }

    Gtk::TreeModelColumn<int> m_col_id;
    Gtk::TreeModelColumn<Glib::ustring> m_col_name;
  };

  ModelColumns m_Columns;

  //Child widgets:
  Gtk::ComboBox m_Combo;
  Glib::RefPtr<Gtk::ListStore> m_refTreeModel;
};

#endif //GTKMM_EXAMPLEWINDOW_H

File: main.cc

#include <gtkmm/main.h>
#include "examplewindow.h"

int main(int argc, char *argv[])
{
  Gtk::Main kit(argc, argv);

  ExampleWindow window;
  //Shows the window and returns when it is closed.
  Gtk::Main::run(window);

  return 0;
}

File: examplewindow.cc

#include "examplewindow.h"
#include <gtkmm/stock.h>
#include <iostream>

ExampleWindow::ExampleWindow()
{
  set_title("ComboBox example");

  //Create the Tree model:
  //m_refTreeModel = Gtk::TreeStore::create(m_Columns);
  m_refTreeModel = Gtk::ListStore::create(m_Columns);
  m_Combo.set_model(m_refTreeModel);

  //Fill the ComboBox's Tree Model:
  Gtk::TreeModel::Row row = *(m_refTreeModel->append());
  row[m_Columns.m_col_id] = 1;
  row[m_Columns.m_col_name] = "Billy Bob";
  /*
  Gtk::TreeModel::Row childrow = *(m_refTreeModel->append(row.children()));
  childrow[m_Columns.m_col_id] = 11;
  childrow[m_Columns.m_col_name] = "Billy Bob Junior";

  childrow = *(m_refTreeModel->append(row.children()));
  childrow[m_Columns.m_col_id] = 12;
  childrow[m_Columns.m_col_name] = "Sue Bob";
  */

  row = *(m_refTreeModel->append());
  row[m_Columns.m_col_id] = 2;
  row[m_Columns.m_col_name] = "Joey Jojo";


  row = *(m_refTreeModel->append());
  row[m_Columns.m_col_id] = 3;
  row[m_Columns.m_col_name] = "Rob McRoberts";

  /*
  childrow = *(m_refTreeModel->append(row.children()));
  childrow[m_Columns.m_col_id] = 31;
  childrow[m_Columns.m_col_name] = "Xavier McRoberts";
  */

  //Add the model columns to the Combo (which is a kind of view),
  //rendering them in the default way:
  m_Combo.pack_start(m_Columns.m_col_id);
  m_Combo.pack_start(m_Columns.m_col_name);

  //Add the ComboBox to the window.
  add(m_Combo);

  //Connect signal handler:
  m_Combo.signal_changed().connect( sigc::mem_fun(*this, &ExampleWindow::on_combo_changed) );

  show_all_children();
}

ExampleWindow::~ExampleWindow()
{
}

void ExampleWindow::on_combo_changed()
{
  Gtk::TreeModel::iterator iter = m_Combo.get_active();
  if(iter)
  {
    Gtk::TreeModel::Row row = *iter;
    if(row)
    {
      //Get the data for the selected row, using our knowledge of the tree
      //model:
      int id = row[m_Columns.m_col_id];
      Glib::ustring name = row[m_Columns.m_col_name];

      std::cout << " ID=" << id << ", name=" << name << std::endl;
    }
  }
  else
    std::cout << "invalid iter" << std::endl;
}

単純なテキストクラスの例

Figure 9.2. ComboBox

ComboBox

Source Code

File: examplewindow.h

#ifndef GTKMM_EXAMPLEWINDOW_H
#define GTKMM_EXAMPLEWINDOW_H

#include <gtkmm/window.h>
#include <gtkmm/comboboxtext.h>

class ExampleWindow : public Gtk::Window
{
public:
  ExampleWindow();
  virtual ~ExampleWindow();

protected:
  //Signal handlers:
  virtual void on_combo_changed();

  //Child widgets:
  Gtk::ComboBoxText m_Combo;
};

#endif //GTKMM_EXAMPLEWINDOW_H

File: main.cc

#include <gtkmm/main.h>
#include "examplewindow.h"

int main(int argc, char *argv[])
{
  Gtk::Main kit(argc, argv);

  ExampleWindow window;
  //Shows the window and returns when it is closed.
  Gtk::Main::run(window);

  return 0;
}

File: examplewindow.cc

#include "examplewindow.h"
#include <gtkmm/stock.h>
#include <iostream>

ExampleWindow::ExampleWindow()
{
  set_title("ComboBoxText example");

  //Fill the combo:
  m_Combo.append_text("something");
  m_Combo.append_text("something else");
  m_Combo.append_text("something or other");

  add(m_Combo);

  //Connect signal handler:
  m_Combo.signal_changed().connect(sigc::mem_fun(*this,
              &ExampleWindow::on_combo_changed) );

  show_all_children();
}

ExampleWindow::~ExampleWindow()
{
}

void ExampleWindow::on_combo_changed()
{
  Glib::ustring text = m_Combo.get_active_text();
  if(!(text.empty()))
    std::cout << "Combo changed: " << text << std::endl;
}