0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

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

Last updated at Posted at 2022-01-20

####TreeViewデータ処理

前回のTreeViewデータ処理の続きです。

#####先頭に一件だけデータを追加する

 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);
  static public void _addFirstRow<T>(this Gtk.ListStore listStore,T obj,int columnName = 0)
    {

        if (listStore.IterNChildren() == 0)
        {
            listStore.AppendValues(obj);
            return;
        }
        
        Gtk.TreeIter iterFirst;
        //先頭のIterを取得する
        listStore.GetIterFirst(out iterFirst);
        //先頭の前のIterを取得する
        Gtk.TreeIter iter = listStore.InsertBefore(iterFirst);
        //Liststoreにセットする
        listStore.SetValue(iter, columnName, obj);
    }

#####最後の行に一件だけデータを追加する

 Gtk.TreeIter iter = musicListStore.Append();
 Song Song1 = new Song ("Daft Punk", "Technologic");
 musicListStore.SetValue(iter, 0, Song1);
    static public void _addRow<T>(this Gtk.ListStore listStore, T obj, int columnNum = 0)
    {
        Gtk.TreeIter iter = listStore.Append();
        listStore.SetValue(iter, columnNum, obj);
    }

#####TreeViewの選択した行の後にデーターを一件追加する

TreeIter iter;
 ITreeModel model;
 if (treeView1.Selection.GetSelected(out model,out iter))
 {   
     Gtk.TreeIter iterAfter = musicListStore.InsertAfter(iter);
     Song Song1 = new Song ("after after", "after after");
     musicListStore.SetValue(iterAfter, 0, Song1);
 }

#####TreeViewの選択した行を削除する

TreeIter iter;
ITreeModel model;
if (treeView1.Selection.GetSelected(out model,out iter))
{
        musicListStore.Remove(ref iter);
}
static public void _deleteSelectedRow<T>(this Gtk.TreeView treeView, Gtk.ListStore listStore)
  {
     TreeIter iter;
     ITreeModel model;
     if (treeView.Selection.GetSelected(out model,out iter))
     {
         listStore.Remove(ref iter);
     }
}

#####TreeViewの選択した行を取得する

private void on_treeViewSection1_changed(object sender , EventArgs e){
	
	TreeIter iter;
	ITreeModel model;
	if (treeView1.Selection.GetSelected(out model,out iter))
	{
		testTable modelData = (testTable)testTableListStore.GetValue(iter, 0);
	}		
}
static public object _getSelectedRow<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;
}

#####ListStoreのRowChangedの処理

 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);
            Console.WriteLine("testModel1" + testModel1  );          
        }
    };

testTableListStore.RowChanged += delegate(object o, RowChangedArgs args)
{
    ListStore testStore = ((ListStore)o);
    testTable testTable1 = (testTable)testStore._getListStoreRowChanged<testTable>(args);
};

 static public object _getListStoreRowChanged<T>(this Gtk.ListStore listStore, RowChangedArgs args)
    {
        TreeIter iter;
        if (listStore.GetIter(out iter, args.Path))
        {
            T model = (T)listStore.GetValue(iter, 0);
            return model;
        }
        return null;
    }

#####Clearを使わずにRowを削除する

ListStore.Clear()はクラッシュすることがあり、代わりの手段

for (int i = 0; i < musicListStore.IterNChildren(); i++) {
	TreeIter iter;
	if (musicListStore.IterNthChild(out iter, i))
	{
  	  musicListStore.Remove(ref iter);
	}
}

if (musicListStore.IterNChildren() > 0)
{
	TreeIter iter;
	if (musicListStore.IterNthChild(out iter, 0))
	{
 	   musicListStore.Remove(ref iter);
	}
}

拡張クラス

 static public void _ClearCustom(this Gtk.ListStore listStore)
    {
        for (int i = 0; i < listStore.IterNChildren(); i++) {
            TreeIter iter;
            if (listStore.IterNthChild(out iter, i))
            {
                listStore.Remove(ref iter);
            }
        }
        if (listStore.IterNChildren() > 0)
        {
            TreeIter iter;
            if (listStore.IterNthChild(out iter, 0))
            {
                listStore.Remove(ref iter);
            }
        }
    }

#####サンプル

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

namespace treeViewTest
{
    public class Song
    {
        public Song (string artist, string title)
        {
            this.Artist = artist;
            this.Title = title;
        } 
        public string Artist;
        public string Title;
    }
    partial class MainWindow
    {

        [UI] private Gtk.TreeView treeView1 = null;
	
        [UI] private Gtk.Button insertAfterBtn = null;
        [UI] private Gtk.Button insertBeforeBtn = null;
	
        [UI] private Gtk.Button appendBtn = null;
	
        [UI] private Gtk.TreeSelection selection1 = null;
        private Gtk.ListStore musicListStore;

        private void on_insertAfterBtn_clicked(object sender , EventArgs e)
        {
            TreeIter iter;
            ITreeModel model;
            if (treeView1.Selection.GetSelected(out model,out iter))
            {   
                Gtk.TreeIter iterAfter = musicListStore.InsertAfter(iter);
                Song Song1 = new Song ("after after", "after after");
                musicListStore.SetValue(iterAfter, 0, Song1);
            }
        }

        private void on_appendBtn_clicked(object sender , EventArgs e){
                
            Gtk.TreeIter iter = musicListStore.Append();
            Song Song1 = new Song ("Daft Punk", "Technologic");
            musicListStore.SetValue(iter, 0, Song1);
        }

		private void on_insertBeforeBtn_clicked(object sender , EventArgs e)
        {

            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);
			
		}

        void _mkTreeView()
        {
            List<Song> songs = new List<Song>();

            songs.Add (new Song ("Dancing DJs vs. Roxette", "Fading Like a Flower"));
            songs.Add (new Song ("Xaiver", "Give me the night"));
            songs.Add (new Song ("Daft Punk", "Technologic"));

            Gtk.TreeViewColumn artistColumn = new Gtk.TreeViewColumn ();
            artistColumn.Title = "Artist";
            Gtk.CellRendererText artistNameCell = new Gtk.CellRendererText ();
            artistColumn.PackStart (artistNameCell, true);

            Gtk.TreeViewColumn songColumn = new Gtk.TreeViewColumn ();
            songColumn.Title = "Song Title";
            Gtk.CellRendererText songTitleCell = new Gtk.CellRendererText ();
            songColumn.PackStart (songTitleCell, true);

            treeView1.AppendColumn (artistColumn);
            treeView1.AppendColumn (songColumn);

            musicListStore = new Gtk.ListStore (typeof (Song));
            
            foreach (Song song in songs) {
                musicListStore.AppendValues (song);
            }

            artistColumn.SetCellDataFunc (artistNameCell, new Gtk.TreeCellDataFunc (RenderArtistName));
            songColumn.SetCellDataFunc (songTitleCell, new Gtk.TreeCellDataFunc (RenderSongTitle));

            treeView1.Model = musicListStore;

        }        
        private void RenderArtistName (Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.ITreeModel model, Gtk.TreeIter iter)
        {
            Song song = (Song) model.GetValue (iter, 0);

            if (song.Artist.StartsWith ("X") == true) {
                (cell as Gtk.CellRendererText).Foreground = "red";
            } else {
                (cell as Gtk.CellRendererText).Foreground = "darkgreen";
            }

            (cell as Gtk.CellRendererText).Text = song.Artist;
        } 
        private void RenderSongTitle (Gtk.TreeViewColumn column, Gtk.CellRenderer cell, Gtk.ITreeModel model, Gtk.TreeIter iter)
        {
            Song song = (Song) model.GetValue (iter, 0);
            (cell as Gtk.CellRendererText).Text = song.Title;
        } 
    }
}

####考察
データを追加更新していく際に、データ全体(配列複数)を全部入れ直しを何度もやっていると、メモリリークやポインタエラーで落ちることがある。
データは一件ずつ先頭や最後に入れて更新していくほうがよい。
データをがちゃがちゃやっていると、ListStore.Clear()を実行する時にアプリが落ちることがある。

#####ListStore.Clear()は頻繁に使うとクラッシュする

バグのようなので代わりの手段で削除する

#####Clear時にはtreeView1.ModelにはNullをいれたほうがよい

Gtk-CRITICAL **: gtk_list_store_iter_next: assertion こののようなエラーがでます。
古いiterがModelの中に残ってていることが起こるエラーのようです。

Gtk3アプリ GtkButton処理関連に続く

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?