LoginSignup
2
0

More than 1 year has passed since last update.

Gtk3アプリ TreeViewとデータ各種処理

Last updated at Posted at 2021-08-21

TreeView関連のデータ各種処理

TreeViewにデーターを入れる

using System;
using Gtk;
using UI = Gtk.Builder.ObjectAttribute;

private Gtk.ListStore testStore;

private void _mkData(){

 testModel testModel1 = new testModel();
 testModel1.aId = 1;
 testModel1.testStr = "aaaaa";

 testStore = new Gtk.ListStore (typeof (testModel));
 testStore.AppendValues (testModel);

 treeView1.Model = testStore;
}

public class testModel
{
    public long aId { get; set; }
    public string testStr { get; set; }
}

TreeViewの表示の仕方について詳しく書いてあります。

データストアのデータを取り出す

データストアにインサートしたデータをForeachで取り出せます。

private Gtk.ListStore testStore;

testStore.Foreach (delegate (ITreeModel model, TreePath path, TreeIter iter)  {
	testModel testModel1 = model.GetValue(iter, 0) as testModel;	
	return false;
});

    static public List<T> _getData<T>(this Gtk.ListStore listStore)
    {
        List<T> objectArray = new List<T>();

        listStore.Foreach((model, path, iter) =>{
            T object1 = (T)model.GetValue(iter, 0);
            objectArray.Add(object1);
            return false;
        });
        return objectArray;
    }

CombBoxの選択したデータを取り出す

private void on_comboBox1_changed(object sender , EventArgs e){

	TreeIter tree;
	comboBox1.GetActiveIter(out tree);
	testModel testModel1 = (testModel)testStore.GetValue (tree, 0);
}

CombBoxの選択したindexを取得設定する

private void on_comboBox1_changed(object sender , EventArgs e){

   int selectedIndex = ((Gtk.ComboBox)sender).Active;
}

comboBox1.Active = 0;

TreeViewのRowを選択しデータを取り出す

GtkTreeSelectionを選択しシグナルを追加する
Screenshot from 2021-08-21 20-13-00.png

AutoConnectした状態にする。
コールバック関数を追加し、GetSelectedを呼び出す

private void on_selection1_Changed(object sender , EventArgs e){		
	
	ITreeModel model;
	TreeIter iter;
	if (treeView1.Selection.GetSelected(out model,out iter))
	{
		testModel testModel1 = (testModel)testStore.GetValue(iter, 0);
	}

}
static public object _getSelectionSelectedRow<T>(this Gtk.TreeView treeView,Gtk.ListStore listStore)
{
        TreeIter iter;
        ITreeModel model;
        if (treeView.Selection.GetSelected(out model,out iter))
        {
            T modelData = (T)listStore.GetValue(iter, 0);
            return modelData;
        }
        return null;
}

チェックボタンからデータを取り出す

private Gtk.ListStore testStore;

void _mkToggle()
{

    Gtk.TreeViewColumn DelColumn = new Gtk.TreeViewColumn ();
    Gtk.CellRendererToggle CellRendererToggle = new Gtk.CellRendererToggle();
    DelColumn.Title = "削除";
    CellRendererToggle.Width = 100;
    DelColumn.PackStart(CellRendererToggle, true);
    
    //イベントハンドラ1
    CellRendererToggle.Toggled += delegate(object o, ToggledArgs args) {
        TreeIter iter;
        if(testStore.GetIterFromString(out iter, args.Path)) {
            testModel testModel1 = (testModel)testStore.GetValue(iter, 0);
        }
    };
    //イベントハンドラ2
    CellRendererToggle.Toggled += new ToggledHandler(testToggled);
}

private void testToggled(object o, ToggledArgs args) {
    TreeIter iter;
    if(testStore.GetIterFromString(out iter, args.Path)) {
	    testModel testModel1 = (testModel)testStore.GetValue(iter, 0);
    }
}
static public object _getToggledRow<T>(this Gtk.ListStore listStore, ToggledArgs args)
{
   TreeIter iter;
   if (listStore.GetIterFromString(out iter, args.Path))
   {
        T modelObj = (T)listStore.GetValue(iter, 0);
        return modelObj;
   }
   return null;
}

TreeViewのCellを編集できるようにする

Gtk.TreeViewColumn artistColumn = new Gtk.TreeViewColumn ();
artistColumn.Title = "Artist";
artistColumn.Expand = true;
artistColumn.Sizing = TreeViewColumnSizing.Autosize;	    
Gtk.CellRendererText artistCellRendererText = new Gtk.CellRendererText ();
artistCellRendererText.Editable = true;
artistCellRendererText.Edited += new EditedHandler(TextCellEdited);

private void TextCellEdited (object o, EditedArgs args)
{
    TreePath treePath1 = new TreePath (args.Path);
    TreeIter iter;
    testStore.GetIter (out iter, treePath1);
    testModel testModel1 = (testModel)testStore.GetValue(iter, 0);
    Console.WriteLine(args.NewText);
}

Listoreのイベントからデータを取り出す

listStore1 = new Gtk.ListStore (typeof (testModel));
listStore1.RowChanged += delegate(object o, RowChangedArgs args)
{
    ListStore testStore = ((ListStore)o);
    TreeIter iter;
    if (testStore.GetIter(out iter, args.Path))
    {
        testModel testModel1 = (testModel)testStore.GetValue(iter, 0);
    }

};

Listoreのイベントからデータを取り出すExtension

   static public List<T> _getData<T>(this Gtk.ListStore list)
    {
        List<T> objectArray = new List<T>();
        list.Foreach((model, path, iter) =>{
            T object1 = (T)model.GetValue(iter, 0);
            objectArray.Add(object1);
            return false;
        });
        return objectArray;
    }

ListStoreのデータソートDescのやり方

やり方1
先頭に一件だけ追加する。
  Gtk.TreeIter iterFirst;
  //先頭のIterを取得する
  musicListStore.GetIterFirst(out iterFirst);
  //先頭の前のIterを取得する
  Gtk.TreeIter iter = musicListStore.InsertBefore(iterFirst);
  Song Song1 = new Song ("test test", "testtest");
  //Liststoreにセットする
  musicListStore.SetValue(iter, 0, Song1);
最後の行の後に一件だけ追加する
 Gtk.TreeIter iter = musicListStore.Append();
 Song Song1 = new Song ("Daft Punk", "Technologic");
 musicListStore.SetValue(iter, 0, Song1);
やり方2

Gtk.TreeModelSortを使ったやり方 (動作させるにはひと工夫必要)
modelの値を指定してDescさせるやり方。

TreeModelSortというクラスを使うと順番を変更できる。

    //ソート やり方2
    //TreeModelSortを使用するやり方
    Gtk.TreeModelSort sortable = new Gtk.TreeModelSort(TestListStore);
            
    sortable.SetSortFunc(0, delegate(
        ITreeModel model, 
        TreeIter iter, 
        TreeIter treeIter){
        TestView s1 = (TestView)model.GetValue(iter, 0);
        TestView s2 = (TestView)model.GetValue(treeIter, 0);
        return DateTime.Compare(s1.Create_date, s2.Create_date);
    });
            
    treeView1.Model = sortable;
ソート やり方1について 
ListStore.Clearを使う時の注意点

ListStore.Clear実行すると以下のエラーが出ることがる。
ITreeModelに登録されたiterがTreeModelの中で消えていないため?
iterはデータや何行目を元にハッシュにしてパスとして使っている?
データの配列の順番を替えたりすると、treeView1.ModelにListStoreを入れるエラーが出ることがある。

Modelのiterの設定を事前にリセットする

TreeView.ModelとListStoreがつながった状態でListStoreのAppendValuesにデータを入れる瞬間に、TreeViewでトリガーで何か関数が走る。iterの設定がおかしいとここでエラーがでる。
Modelにnullを入れることでModelの中のiterの設定をリセットしておく

Gtk-CRITICAL **: gtk_list_store_iter_next: assertion
'priv->stamp == iter->stamp' failed

Gtk-CRITICAL **: gtk_tree_path_to_string: assertion
'path != NULL' failed

Gtk-CRITICAL **: gtk_list_store_get_value: assertion
'iter_is_valid (iter, list_store)' failed
ポイント

Nullを入れてやる。その後ListStorをClearする

treeView1.Model = null;
ListStore.Clear();

OK
gtk_tree_path_to_string系のエラーはModelにnullを入れたら消えた。

Gtk-CRITICAL **:gtk_tree_path_to_string: assertion 'path != NULL' failed
treeView1.Model = null;

データーをがちゃがちゃいじりすぎるとClear時にエラーが起きます。
データーは一件ずつ先頭や最後に入れていくのがよいです。
Clearの後にはModelにnullを入れておいたほうがよい。

追記
UIの更新で注意点
Webなどの非同期処理の中で一緒にUIを更新するとクラッシュすることがありました。
UIの更新は同期のしたほうが安定していて確実です。

Gtk3アプリのTreeViewの表示の簡略化 Part2に続く

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0