####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の中に残ってていることが起こるエラーのようです。