retireSakiの日記

たぶん引退した?ソフトウエアエンジニアのブログ

GTKmm (3.0) と glade によるアプリ (13) - 簡単なツリービューを表示

 今回は、簡単なツリービューの表示、展開と折りたたみなどを行います。

◆折りたたみ時

f:id:retireSaki:20181124145511j:plain

◆展開時

f:id:retireSaki:20181124145526j:plain

 ツリービュー内のデータは、初期化処理内で固定したデータを設定しますが、ボタンをクリックすることで、全てのアイテムを展開または折りたたみます。
展開時にツリービューの表示領域範囲を超える場合、自動的にスクロールバーを表示するようにします。

ソースコードは最後に両方の機能を含めたものを公開。(zipダウンロードできます)

A. glade の編集

f:id:retireSaki:20181124145543j:plain

 今回はメインウィンドウのみの構成です。
詳細はダウンロードして、paned_test.glade を確認してください。
f:id:retireSaki:20181124145742p:plain GtkTreeView を GtkScrolledWindow 内に設置することで、ツリービューが現在のWidgetサイズを超える時、自動的にスクロールバー&スクロール処理を行うようになります。


B. MainWindow.h の編集


● MainWindow.h

class TreeRecords : public Gtk::TreeModel::ColumnRecord
{

public:
    Gtk::TreeModelColumn< Glib::ustring > m_col_name;

    TreeRecords () {
        add( m_col_name );
    }
};
…
class MainWindow : public Gtk::ApplicationWindow
{
…
protected:
…
    Gtk::TreeView *m_treeview = nullptr;

    Gtk::Button *m_btn_expandall = nullptr;
    Gtk::Button *m_btn_collapseall = nullptr;

    TreeRecords m_record;
    Glib::RefPtr< Gtk::TreeStore > m_treestore;

private:
…
    void on_btn_expandall_clicked()
    {
        m_treeview->expand_all();
    }
    void on_btn_collapseall_clicked()
    {
        m_treeview->collapse_all();
    }
…

1) ツリービューのカラム処理用クラス TreeRecords の定義。

 レコードの m_col_name が設定されると、ツリービューに設定された m_col_name の行を追加します。

2) on_btn_expandall_clicked() 関数

 TreeView::expand_all() を使って、全てのアイテムを再帰的に展開します。

3) on_btn_collapseall_clicked() 関数

 TreeView::collapse_all() を使って、全てのアイテムを再帰的に折りたたみます。


C. MainWindow.cc の編集


● MainWindow.cc

void MainWindow::setInit_display()
{
…
    refBuilder->get_widget("treev_View1", m_treeview);

    // get widget
    refBuilder->get_widget("btn_expandall", m_btn_expandall);
    refBuilder->get_widget("btn_collapseall", m_btn_collapseall);
…
    // button signals
    m_btn_expandall->signal_clicked().connect(
        sigc::mem_fun(*this, &MainWindow::on_btn_expandall_clicked) );
    m_btn_collapseall->signal_clicked().connect(
        sigc::mem_fun(*this, &MainWindow::on_btn_collapseall_clicked) );

    m_treestore = Gtk::TreeStore::create( m_record );
    m_treeview->set_model( m_treestore );

    m_treeview->append_column( "name", m_record.m_col_name );

    Gtk::TreeModel::Row row;

    // root
    row = *( m_treestore->append() );
    row[ m_record.m_col_name ] = "root 1";

    Gtk::TreeModel::Row parent_row = row;
    row = *( m_treestore->append( parent_row.children() ) );
    row[ m_record.m_col_name ] = "sub 1";

    row = *( m_treestore->append( parent_row.children() ) );
    row[ m_record.m_col_name ] = "sub 2";

    row = *( m_treestore->append( row.children() ) );
    row[ m_record.m_col_name ] = "sub-sub 1";

    row = *( m_treestore->insert_after( row ) );
    row[ m_record.m_col_name ] = "sub-sub 2";

    row = *( m_treestore->insert_after( row ) );
    row[ m_record.m_col_name ] = "sub-sub 3";

    row = *( row.parent() );
    row = *( m_treestore->insert_after( row ) );
    row[ m_record.m_col_name ] = "sub3 ";

    row = *( m_treestore->append( row.children() ) );
    row[ m_record.m_col_name ] = "sub-sub 4";

    row = *( m_treestore->insert_after( row ) );
    row[ m_record.m_col_name ] = "sub-sub 5";

    row = *( row.parent() );
    row = *( m_treestore->insert_after( row ) );
    row[ m_record.m_col_name ] = "sub4 ";

    // root
    row = *( m_treestore->append() );
    row[ m_record.m_col_name ] = "root 2";

    row = *( m_treestore->append( row.children() ) );
    row[ m_record.m_col_name ] = "sub 5";
}
…

 今までさんざんやってきたことなので、詳しい説明は必要ないですね。

1) ツリービューの設定

(1.1) TreeStore::create() を使い、TreeRecords クラスをインスタンス化します。

 static Glib::RefPtr Gtk::TreeStore::create
    ( const TreeModelColumnRecord& columns );

(1.2) TreeView::set_model() を使って、ツリービューに m_treestore をモデルとして設定します。

 void Gtk::TreeView::set_model ( const Glib::RefPtr< TreeModel >& model );

(1.3) TreeView::append_column() を使い、ツリービューに m_record.cell を含む title 名のカラムを作成・追加します。

 int Gtk::TreeView::append_column
   ( const Glib::ustring & title, CellRenderer& cell );

2) ツリービューにデータを設定
 設定しているデータがどの親に所属しているか注意しながら、データを設置します。
 今回は列が1つだけなので、名前の設定だけになっています。

(2.1) TreeStore::prepend() 関数を使い、トップレベルの行を作成します。

  iterator Gtk::TreeStore::prepend ( );

 作成した行の TreeRecords::m_col_name に文字列をセットすることで、行に文字列のカラムを追加します。

(2.2) TreeStore::append() 関数を使って、指定した行を追加します。
 このとき、node に Gtk::TreeModel::Row に対して TreeModel::children() 関数を使うことで、指定したRow の子を作成します。

  iterator Gtk::TreeStore::append ( const TreeNodeChildren& node );

  Children Gtk::TreeModel::children ( );

 作成した行の TreeRecords::m_col_name に文字列をセットすることで、行に文字列のカラムを追加します。

(2.3) (2.1)(2.2) を繰り返し使うことでツリー内の行を作成します。


以上、ツリーやモデル、ストアの関係が面倒ですが、意外と簡単でしたね!

最後に、全てのファイルを圧縮したファイル(zip)を載せます。

●ソース一式

www.mediafire.com

GTKプログラミングを学習するなら!

Gtk+3入門

Gtk+3入門

GTK+・GDKによるLinuxアプリケーション開発 (New riders)

GTK+・GDKによるLinuxアプリケーション開発 (New riders)

Learn GTK# Programming

Learn GTK# Programming

注目記事

「Amazon.co.jpアソシエイト」または「[乙の名称を挿入]は、Amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイトプログラムである、Amazonアソシエイト・プログラムの参加者です。