Gtk::TreeViewでリスト表示をする
C++で GTKアプリケーションを作る例が世の中に少なすぎてサンプルを探すのに苦労するので自分でネットに上げておく
2021年9月28日 嶋田大貴
「ツリービューでリスト表示したい三銃士を連れてきたよ」
「えっ、C++でGTKを!?」
「インタラクション担当、Gtk::TreeView」
「型定義担当、Gtk::TreeModelColumnRecord」
「データストア担当、Gtk::ListStore」
カラム数分の Gtk::TreeModelColumn<T> を作って Gtk::TreeModelColumnRecordオブジェクトに addしたらそれを使って Gtk::ListStoreを構築、さらにそれを Gtk::TreeView に set_modelする。さらに TreeViewに対してもカラムごとにappend_columnでモデルとの紐付けと当時にタイトルの設定をする必要がある。行の追加操作やイテレーションなどは ListStoreに対して行う。
カラムの型によって自動的にそれ用のレンダラーが選択されるあたり、張り切ってC++していると言える。(boolのカラムに注目)
ユーザーがリストのアイテムを選択した時のイベントを拾うには TreeViewの signal_cursor_changed シグナルを使う。
// GTK4
#include <iostream>
#include <gtkmm.h>
class MainWindow : public Gtk::Window {
Gtk::Box box;
Gtk::Button button;
Gtk::TreeView treeview;
Gtk::TreeModelColumnRecord columnrecoed;
struct {
Gtk::TreeModelColumn<std::string> col1;
Gtk::TreeModelColumn<bool> col2;
Gtk::TreeModelColumn<int> col3;
} columns;
Glib::RefPtr<Gtk::ListStore> liststore;
public:
MainWindow();
virtual void on_realize();
void erase_items_have_even_num();
};
MainWindow::MainWindow() : box(Gtk::Orientation::VERTICAL)
{
columnrecoed.add(columns.col1);
columnrecoed.add(columns.col2);
columnrecoed.add(columns.col3);
liststore = Gtk::ListStore::create(columnrecoed);
treeview.set_model(liststore);
treeview.append_column("文字列", columns.col1);
treeview.append_column("真偽値", columns.col2);
treeview.append_column("整数", columns.col3);
treeview.signal_cursor_changed().connect([this]() {
auto selected_row = treeview.get_selection()->get_selected();
if (selected_row) {
std::cout << selected_row->get_value(columns.col1) << " selected." << std::endl;
}
});
box.append(treeview);
button.set_label("偶数のやつを消す");
button.signal_clicked().connect([this]() { erase_items_have_even_num(); });
box.append(button);
set_child(box);
}
void MainWindow::on_realize()
{
Gtk::Window::on_realize();
liststore->clear();
auto row = *liststore->append();
row[columns.col1] = std::string("ぼぎゃー");
row[columns.col2] = true;
row[columns.col3] = 123;
row = *liststore->append();
row[columns.col1] = std::string("もげー");
row[columns.col2] = false;
row[columns.col3] = 456;
}
void MainWindow::erase_items_have_even_num()
{
auto i = liststore->get_iter("0");
while (i) {
if (i->get_value(columns.col3) % 2 == 0) {
i = liststore->erase(i);
} else {
i++;
}
}
}
int main(int argc, char* argv[])
{
auto app = Gtk::Application::create("com.walbrix.simple_list_using_treeview");
return app->make_window_and_run<MainWindow>(argc, argv);
}
// g++ -std=c++20 -o simple_list_using_treeview simple_list_using_treeview.cpp `pkg-config --cflags --libs gtkmm-4.0`
記事へのコメントは Twitterにお願いします。
2021年9月28日 嶋田大貴