ゲームエフェクトデザイナーのブログ | A Real-Time VFX Artist's Blog

About Making Materials on UE, Making Tools with C#, etc

C# XMLへの階層構造の保存メモ3(TreeView編)

前回に続き、今度は実践編ということで元々やりたかったことを再帰処理で行ってみます。

フォームはこんな感じ。
あらかじめTreeViewに適当に孫以上の深い階層を追加しておきます。

f:id:moko_03_25:20190610235639j:plain

実装はこんな感じ。
using System.Xml.Linq;」を先頭に追加するのをお忘れなく。。

private void Form1_Load(object sender, EventArgs e)
{
	// ツリーを全て展開
	treeView1.ExpandAll();
}

private void Button1_Click(object sender, EventArgs e)
{
	XmlSave();
}

private void XmlSave()
{
	// XMLの内容の定義
	var xml = new XDocument(new XDeclaration("1.0", "utf-8", "yes"));

	// 構造ごとの要素を定義
	XElement Sample = new XElement("サンプル");
	xml.Add(Sample);

	// TreeViewのノード情報をnodesコレクションに格納
	TreeNodeCollection nodes = treeView1.Nodes;
	// ループ
	foreach (TreeNode node in nodes)
	{
		// 自分自身のノードを定義  
		XElement n = new XElement("ルートノード");
		xml.Root.Add(n);

		// 再帰処理用
		XmlRecursive(node, n);
	}

	// TextBox1に表示
	textBox1.Text = xml.Declaration.ToString();
	textBox1.Text = xml.ToString();
}

// 再帰処理用
private void XmlRecursive(TreeNode node, XElement n)
{
	XElement name = new XElement("Name", node.Text);
	n.Add(name);

	// ループ
	foreach (TreeNode tn in node.Nodes)
	{
		// 自分自身のノードを定義  
		XElement n2 = new XElement("子ノード");
		n.Add(n2);

		// 自分自身を呼び出す
		XmlRecursive(tn, n2);
	}
}

結果はこんな感じ。

f:id:moko_03_25:20190610235658g:plain

ノードのラベル名は<Name>タグに格納しています。
同じように、ノードに紐づけたクラスインスタンスの情報‥例えばノードと紐づけたTextBoxの内容など色々な情報をタグにして埋め込むことができます。

これが不要で単純にノードのラベル名がそのままタグ名になるだけで良いなら、こんなまわりくどくする必要は無くて、もっと簡略化できると思います。

ちなみに文字列をXMLに書き出す際、改行が失われてしまいます。
なので改行を表す特殊文字に置き換えて読み書きすることで対応しました。
「memo.Text.Replace("\r\n", "[:NL:]");」みたいな感じです。
タブスペースは何もしなくても保持されました。

置換の方法はこちらをどうぞ。

XMLの書き出しは初めて試した状態なので、もっと良い方法があればぜひコメントくださいっ。

C# XMLへの階層構造の保存メモ2(TreeView編)

前回に続き、今回はTreeViewのラベル名をXMLへ書き出してみます。

こちらに再帰処理で全てのノード名を取得するサンプルが記載されています。

こちらを参考に少しずつ進めてみました。

まずはフォームを用意してあらかじめTreeViewにノードを登録しておきました。

f:id:moko_03_25:20190609185007j:plain

ボタンクリックイベントでルートノードのラベル名をXMLで書き出してみました。
例によって「using System.Xml.Linq;」を先頭に追加するのをお忘れなく。。

private void Form1_Load(object sender, EventArgs e)
{
	// ツリーを全て展開
	treeView1.ExpandAll();
}

private void Button1_Click(object sender, EventArgs e)
{
	XmlSave();
}

public void XmlSave()
{
	// XMLの内容の定義
	var xml = new XDocument(new XDeclaration("1.0", "utf-8", "yes"));

	// 構造ごとの要素を定義
	XElement 学校;
	XElement クラス;
	XElement 生徒;

	// <私立ほにゃ高校>タグを作成してxmlに追加
	学校 = new XElement("私立ほにゃ高校");
	xml.Add(学校);

	// TreeViewのノード情報をnodesコレクションに格納
	TreeNodeCollection nodes = treeView1.Nodes;

	// ルートノードに対するループ処理
	foreach (TreeNode node in nodes)
	{
		// < クラス > タグを作成してRoot(つまり学校)に追加
		クラス = new XElement(node.Text);
		xml.Root.Add(クラス);
	}

	// TextBox1に表示
	textBox1.Text = xml.Declaration.ToString();
	textBox1.Text = xml.ToString();
}

うまくいきました。

f:id:moko_03_25:20190609184916j:plain

次にルートノードのひとつ下の階層を<生徒>タグ、そしてさらにその下に<名前>タグの入れ子にしてXMLに書き出してみました。

public void XmlSave()
{
	// XMLの内容の定義
	var xml = new XDocument(new XDeclaration("1.0", "utf-8", "yes"));

	// 構造ごとの要素を定義
	XElement 学校;
	XElement クラス;
	XElement 生徒;

	// <私立ほにゃ高校>タグを作成してxmlに追加
	学校 = new XElement("私立ほにゃ高校");
	xml.Add(学校);

	// TreeViewのノード情報をnodesコレクションに格納
	TreeNodeCollection nodes = treeView1.Nodes;

	// ルートノードに対するループ処理
	foreach (TreeNode node1 in nodes)
	{
		// < クラス > タグを作成してRoot(つまり学校)に追加
		クラス = new XElement(node1.Text);
		xml.Root.Add(クラス);

		// 子ノードに対するループ処理
		foreach (TreeNode node2 in node1.Nodes)
		{
			// <生徒>タグを作成して名前をぶら下げてから<クラス>タグに追加
			生徒 = new XElement("生徒");
			生徒.Add(new XElement("名前", node2.Text));
			クラス.Add(生徒);
		}
	}

	// TextBox1に表示
	textBox1.Text = xml.Declaration.ToString();
	textBox1.Text = xml.ToString();
}

うまくいきました。

f:id:moko_03_25:20190609190953j:plain

いよいよ本番である再帰処理は次の記事にまとめました。

C# XMLへの階層構造の保存メモ1(基本編)

C#XMLファイルに親・子・孫‥といった階層構造を書き込みたい場合についてのメモです。

そもそもXMLを初めて扱うので基礎的なあたりを解説している記事を探して参考にしたのですが、こちらがとても入門として分かりやすくてオススメです。


という訳で試してみました。
Windowsフォームアプリでボタンをテキストボックスを配置。

f:id:moko_03_25:20190609152105j:plain

中身はこちらのように記述。
自分でも理解しやすいように、学校>クラス>名前と住所‥という内容にしました。
using System.Xml.Linq;」を先頭に追加するのをお忘れなく。。

private void Button1_Click(object sender, EventArgs e)
{
	XmlSave();
}

public void XmlSave()
{
	// XMLのヘッダー情報
	XDeclaration ヘッダー = new XDeclaration("1.0", "utf-8", "yes");
	// XMLの内容の定義
	XDocument xml = new XDocument(ヘッダー);

	// 学校の要素を定義
	XElement 学校;
	// <私立ほにゃ高校>タグを作成
	学校 = new XElement("私立ほにゃ高校");

	// 学校の要素をxmlに追加(これがRootになる)
	xml.Add(学校);

	// クラスの要素を定義
	XElement クラス;

	// <一組>タグを作成
	クラス = new XElement("一組");
	// <一組>タグに<名前>タグと<住所>タグをデータ込みでぶら下げる
	クラス.Add(new XElement("名前", "石坂"));
	クラス.Add(new XElement("住所", "静岡"));
	// Root(つまり学校)にぶら下げる
	xml.Root.Add(クラス);

	// <二組>タグを作成
	クラス = new XElement("二組");
	// <二組>タグに<名前>タグと<住所>タグをデータ込みでぶら下げる
	クラス.Add(new XElement("名前", "太郎"));
	クラス.Add(new XElement("住所", "福岡"));
	// Root(つまり学校)にぶら下げる
	xml.Root.Add(クラス);

	// TextBox1に表示
	textBox1.Text = xml.Declaration.ToString();
	textBox1.Text = xml.ToString();
}

 実行してbutton1を押すとtextBox1にバッチリ表示されました!

f:id:moko_03_25:20190609152112j:plain

ただし、実際にはもうちょっと複雑な構造‥例えばこんな感じにしたいですよね。

学校
 クラス
  先生
   名前
  生徒
   名前
  生徒
   名前
 クラス
  先生
   名前
  生徒
   名前


この場合はこちらのように記述すればOKです。

private void Button1_Click(object sender, EventArgs e)
{
	XmlSave();
}

public void XmlSave()
{
	// XMLの内容の定義
	var xml = new XDocument(new XDeclaration("1.0", "utf-8", "yes"));

	// 構造ごとの要素を定義
	XElement 学校;
	XElement クラス;
	XElement 先生;
	XElement 生徒;

	// <私立ほにゃ高校>タグを作成してxmlに追加
	学校 = new XElement("私立ほにゃ高校");
	xml.Add(学校);

	// <クラス>タグを作成してRoot(つまり学校)に追加
	クラス = new XElement("クラス");
	xml.Root.Add(クラス);
	// <先生>タグを作成して名前をぶら下げてから<クラス>タグに追加
	先生 = new XElement("先生");
	先生.Add(new XElement("名前", "浅野先生"));
	クラス.Add(先生);
	// <生徒>タグを作成して名前をぶら下げてから<クラス>タグに追加 * 人数分
	生徒 = new XElement("生徒1");
	生徒.Add(new XElement("名前", "飯尾"));
	クラス.Add(生徒);
	生徒 = new XElement("生徒2");
	生徒.Add(new XElement("名前", "上田"));
	クラス.Add(生徒);

	// <クラス>タグを作成してRoot(つまり学校)に追加
	クラス = new XElement("クラス");
	xml.Root.Add(クラス);
	// <先生>タグを作成して名前をぶら下げてから<クラス>タグに追加
	先生 = new XElement("先生");
	先生.Add(new XElement("名前", "江原先生"));
	クラス.Add(先生);
	// <生徒>タグを作成して名前をぶら下げてから<クラス>タグに追加 * 人数分
	生徒 = new XElement("生徒1");
	生徒.Add(new XElement("名前", "大谷"));
	クラス.Add(生徒);

	// XMLファイルに保存する
	xml.Save(@"sample.xml");

	// TextBox1に表示
	textBox1.Text = xml.Declaration.ToString();
	textBox1.Text = xml.ToString();
}

実行してみると、うまくいきました!

f:id:moko_03_25:20190609161443j:plain

躓いた点が一つあったのですが、<クラス>タグの定義の部分を「クラス = new XElement("クラス", "一組");」といったように値を入れてしまうと、階層構造が崩れました。子をぶら下げる箱として用意する場合には値を入れたらダメなんですかね。。

続きはこちら

C# XMLファイルを読み込んでTreeViewにノードを追加する

XMLについての基本的なあたりはこちらの記事を参考にさせていただきました。

標準でクラスが用意されていてこんなにお手軽に読み書きできるとは!

ただ、XML入れ子構造になっていて孫要素が1つの親の中に複数ある場合にどう記述したら良いのかに詰まって結構時間を消費してしまいました。。

‥とそんな中、まさに探していたサンプルが!

しかもすごくシンプルです。これで良かったのかあ~~。

という訳でこのようにうまくいきました!

f:id:moko_03_25:20190609033620g:plain

Teratailで質問した際の回答も、なるほどこれでいけるのね!と。。
https://teratail.com/questions/193924

それから「再帰処理」をちゃんと調べてみました。

こちらC#の調べものでよくお世話になるサイトですが、再帰処理についてのスライドがとても分かりやすかったです。

それからXMLの操作を調べるとLINQを使った記述が沢山出てくるのですが、未だにLINQをちゃんと勉強してないんでそろそろやらないとなと。。

ただ、先月にSQLを一通りやったのが少し役立ってる感じがあります。

あとXML周りを覚えるにもこちらの書籍が良いようで、レビューを色々読んでみても入門を終えた人向けにとても良書と評価されていて購入を考えています。

実戦で役立つ C#プログラミングのイディオム/定石&パターン

実戦で役立つ C#プログラミングのイディオム/定石&パターン

 

Kindle版はこちら。


その他の情報もペタリ。

XElement Class (System.Xml.Linq) | Microsoft Docs

C# TreeViewのノードに対応した文字列をTextBoxに表示する

TreeViewとTextBoxを連動させてツリー構造のテキストエディタを作成中ですが、TreeViewのノードごとにTextBox.Textの内容を記憶させておかないといけません。

その方法についてメモっておきます。ちなみに対応後はこんな感じ。

f:id:moko_03_25:20190608162656g:plain

まず、テキストの内容などを保持しておくためのデータ保持クラスを用意します。

そしてフィールドなりプロパティで下記のような情報を保持する箱を用意します。

・ノードのラベル名 string型
・TextBoxの内容 string型
・キャレットの位置 int型

クラスの内容はこれだけでOKです。

次にMainFormの方に、新しくノードを追加する関数を用意します。

その際にTreeViewのノードのTagに対して、先ほど作成したデータ保持クラスのインスタンスを代入すれば、追加したノードごとにインスタンスを保持してくれます。

ここにテキストの内容を保存したり逆に表示したりすれば良い訳です。

こちらの記事が参考になるかと思います。

問題はノードの選択を変えた時にどのイベントを利用するかですが「BeforSelect」と「AfterSelect」を利用すれば良いようです。

・TreeView1_BeforeSelect イベント
 選択中のノードのTagからデータ保持クラスのインスタンスを取得
 TextBox.Textをインスタンスのフィールドやプロパティに代入

・TreeView1_AfterSelect イベント
 選択中のノードのTagからデータ保持クラスのインスタンスを取得
 インスタンスのフィールドやプロパティからTextBox.Textに代入

これでOKです。

ただし注意点がいくつかあります。

・新規ノード追加時に「BeforSelect」と「AfterSelect」が邪魔
 こちらは新規ノード追加時のフラグを用意しておき‥
 それぞれのイベントは新規ノード追加時には実行しないようにすればOKです。

・ルートノードを削除したような際に例外が発生する
 削除時は削除した直後の内容をデータ保持クラスに保存しようとしたりするので‥
 選択中のノードが null なら保存処理を実行しないようにします。

以上のような対処でひとまずうまく動作しました。

C# TreeViewの主なプロパティ

TreeViewはエクスプローラのナビゲーションウインドウのようにフォルダ階層をツリー表示するようなコントロールです。

ツリーに並ぶアイテムを「ノード」という呼称になります。

 

動作

●FullRowSelect
ノード選択時にTreeViewの幅全体をハイライトします。
ノード名の長さにハイライトの長さが左右されないようTrue推奨です。

●HideSelection
フォーカスが移ったら選択中のノードのハイライトを消します。
今何を選択しているのか分からなくなるのでFalse推奨です。

●Indent
ノードのインデントの設定。ただしデフォルトの19が丁度良いです。

●LabelEdit
ユーザーがノードのラベル名を編集できるようにします。
選択中のノードをさらにクリックすると編集可能状態になります。
ラベル名変更ダイアログなど自作しなくて済むのでTrue推奨です。
F2キーで編集可能にするにはそのように実装する必要があります(後述)。

●ShowLines
ノードの階層をラインで表示します。
シンプルな見た目にしたい場合はFalseで。

 

表示

●BackColor
背景色

●Font
ノードのラベルで表示される文字のスタイル

●BorderStyle
コントロールの枠線のスタイル。

●ForeColor
ノードのラベルの文字色。

 

よく使うコード例


ノードを追加する場合

 // ノードの生成
TreeNode インスタンス名 = new TreeNode(ラベルの文字列);

// 生成したノードの追加
treeView1.Nodes.Add(インスタンス名);

// 追加したノードを選択
treeView1.SelectedNode = インスタンス名;


ノードが選択されているか調べる場合

// ノードを選択しているかどうかを判定
if (treeView1.SelectedNode != null)

// 親ノードが存在するか判定
if (treeView1.SelectedNode.Parent == null)


選択中のノードに子ノードを追加

// 空のノードを生成
TreeNode 子のインスタンス名 = new TreeNode(子のラベルの文字列);

// 選択中の親ノードをインスタンスに代入
TreeNode 親のインスタンス名 = treeView1.SelectedNode;

// 親ノードに子ノードを追加
親のインスタンス名.Nodes.Add(childNode);

// 親のツリーを開く
親のインスタンス名.Expand();


親ノードを選択

// 空のノードを生成
TreeNode インスタンス名 = new TreeNode();

// 選択中のノードの親をインスタンスに代入
インスタンス名 = treeView1.SelectedNode.Parent;

// ラベル名を取得
string s = インスタンス名.Text;


選択中のノードを削除

// 選択中のノードを削除
treeView1.SelectedNode.Remove();


ノードをindexで指定する

// 0 番目のノード
treeView1.Nodes[0];


ルートノードの数をカウントする

// ルートノードの数をカウント
int i = treeView1.Nodes.Count;


選択中のノードと同じ親のノードをカウントする

// 同じ親に属するノードの数をカウント
TreeNode インスタンス名 = treeView1.SelectedNode;
int i = インスタンス名.Nodes.Count;


ノードにオブジェクトを渡す

// 空のノードを生成
var インスタンス名 = new クラス();

// 空のノードを生成
rootNode.Tag = fData;


ラベル名編集関連はこちらの記事が参考になります。

TreeViewのノードのテキストをユーザーが編集できるようにする - .NET Tips (VB.NET,C#...)

ツリーをドラッグ&ドロップで操作したい場合について。

TreeViewのノードをDrag&Dropにより移動、コピーできるようにする - .NET Tips (VB.NET,C#...)

 

※随時更新

C# Formの主なプロパティ

よく忘れるのでメモ。

 

ウインドウスタイル

●Icon
フォームタイトルとタスクバーに表示するアイコンを指定。

●MaximizeBox
最大化するか。

●MinimizeBox
最小化するか。

●ShowIcon

フォームのタイトルに表示されるアイコンの表示。 

●ShowInTaskbar
タスクバーに表示するか。

●TopMost
フォームを最前面に表示するか。 

 

動作

●AllowDrop
フォームへのファイルのドロップを受け付けるか。

 

配置

●MaximumSize
見た目的に許せる範囲で最大サイズを設定したい場合に設定。

●MinimumSize
人によってはコンパクトにして使いたい人もいるので、フォームの見た目的に許せる範囲で最小サイズを設定しておくと良い。

●StartPosition
起動時の初期位置を指定。CenterScreenだと中央に表示される。

 

表示

●BackColor
背景色。

●Font
フォームのタイトルの文字のスタイル。

●FormBorderStyle
フォーム外観の設定。一番重要。
Noneの場合は最小化・最大化・サイズ変更などを別途記述する必要がある。

●Text
タイトルとタスクバーに表示される文字列。
なのでフォームの外観を枠無しにした場合もちゃんと設定しておく。

 

フォーム外観をNoneにした際に、マウスドラッグでフォームのサイズを変更できるようにするには、こちらの記事を参考にさせていただいています。

C#でWPFを始める

C#Windowsフォームアプリを作っていると、特にグラフィックデザイナを生業としている身の場合にコントロールの標準のプロパティでは大して外観を変えることができずに「かゆいところに手が届かない!」感がストレスになってきます。

そこで「それならWFPかなあ」と手を出していきたいと思った場合に、ある程度まとまったチュートリアル記事が用意されているこちらの入門記事が良さそうです!

XAMLの書き方についてはUdemyのこちらのレッスンがおすすめ。

WPFは一般にはあまり普及していないイメージがありつつも、まとまった情報は探すとたまに出てきますね。。

という訳でとりあえずのメモでした。

更新していくかも知れません。

Cドライブの圧迫の原因を調べてお掃除した際のメモ

Cドライブの容量を削減したい場合にはいつも「DiskInfo」を利用しています。

こちらで各階層のフォルダごとに容量を圧迫しているものが一目で特定できます。

私が3年以上使用していたデスクトップマシンでは‥

●C:\Windows.old が 38GB ほど圧迫

こちらの記事を参考にディスククリーンアップで削除しました。


●C:\Autodesk\WI が 7.18GB ほど圧迫

削除して良さそうだったので削除しました。


MayaLT2018 が 1.55GB ほど圧迫

たまに1ヵ月だけMayaLTを契約して使うことがありますが、MayaLT2018 が 1.55GBほど圧迫していたので当面不要ならアンインストールするのも良いかと思います。

Visual Studio の各コンポーネント

インストール時にあらゆる開発環境をインストールすると全部で46GBに及んだりします。下記の記事に何がどれくらい容量を圧迫するか書いています。


ウェブアプリの開発環境

それから「プログラムの追加と削除」でサイズ順に並べると、ウェブアプリの開発環境関連のアプリケーションが思いのほか容量を占めています。

Ruby 2.6.3 ‥ 905MB
Vagrant ‥ 862MB
Java SE Development Kit 8 Update 121 ‥ 308MB
Java 8 Update 161 ‥ 100MB
Oracle VM VirtualBox 6.0.6 ‥ 235MB
Microsoft SQL Server 2016 LocalDB ‥ 233MB
MySQL Installer ‥ 429MB
MySQL Server 5.7 ‥ 319MB
MySQL Workbench 8.0 CE ‥ 126MB
MySQL Connector C++ 8.0 ‥ 115MB
MySQL Shell 8.0.16 ‥ 106MB
MySQL Router 8.0 ‥ 89MB
MySQL Documents 5.7 ‥ 79MB
MySQL Connector/ODBC 8.0 ‥ 54MB


また、Pythonの開発環境である Anaconda3 (C:\Users\<ユーザ名>\Anaconda3) がなんと 5.6GB ほど圧迫しています(!)。

VirtualBox などの仮想環境でちゃんと構築&管理しておけば、後になって「当面は開発環境いらないな~」となったら楽にアンインストールできるんでしょうか。

●C:\Program Files

Unity・Trend Microdotnet・Side Effects Software・NVIDIA Corporation・Autodeskあたりが1~3GBほど圧迫。

●C:\Program Files (x86)

Microsoft Office・Common Files・Steamなどのフォルダが1~3GBほど圧迫。

ちなみにUnreal EngineAdobe製品はDドライブにインストールしています。
UE_4.22フォルダは25.1GBありました。。

●C:\Windows\Installer が 8.5GB ほど圧迫

どうも手動では消せないようでフリーソフトが必要とのこと。
いくつかのサイトで「Patch Cleaner」が紹介されていました。
インストーラをDLしてのインストールが必要なようなので保留。。

●C:\Windows\WinSxS が 7.7GB ほど圧迫

5万を超えるファイル数でした。
ディスククリーンアップはすでに行っていてこの状態なので、下記の記事を参考にコマンドプロンプトを管理者権限で実行して「C:\Windows」に移動して、コマンド「DISM /OnLine /Cleanup-Image /StartComponentCleanup /ResetBase」を試してみました。

6.47GBになりました。1.3GBほど減った感じでしょうか。。
手動で消すと危険なフォルダみたいなので一旦これで放置。

●c:\Windows\System32\DriverStore が 1.2GB ほど圧迫

検索してみると人によっては10GBとか圧迫しているようですね。
私の場合は 1.2GB程度なのと、手動では消せずフリーソフトが必要なようなので放置。


●C:\Users\<ユーザ名>\Documents\My Kindle Content が 1.6GB ほど圧迫

Kindle for PC でDLしたものだと思うのでやむなし。

●C:\Users\<ユーザ名>\AppData が 9.7GB ほど圧迫

「Local」と「Roaming」がよく圧迫の原因になっています。
たまに整理しているため10GBいかない程度でした。

今確認してみたところではChromeFirefoxがキャッシュで圧迫している他、Atomが1GB使ってたり(パッケージのインストールとかが原因?)、あとはUnreal Engineが過去バージョンの何かしらの情報を保持しているようだったのでもう使わないバージョンのフォルダを削除。

という感じで今回は合計 50GB ほどお掃除ができました!

自宅のデスクトップマシンのCドライブは現状 222GB しか無いので、これでまたしばらくの間は作業に耐えられそうです。

ノートPCでメモを取ることについて

うちのヨメさんは「世界一受けたい授業」が好きなのですが、つい先日「めちゃ面白いから観て!」と前田裕二さんが取り上げられた回の録画を半ば強制的に見させられ、この方にとても興味が湧きました。一日に書くメモの量が尋常じゃないですね。

触発されたヨメはすでに前田さんの著書『メモの魔力』を買っており、自分はそれを借りて今はまだ読み始めた段階なのですが、文章から溢れる熱量もすごいですが読者に対する誠実さみたいなものも強く感じられます。

特に付録の自己分析1000問インパクトも強く、読み終えたら回答していきたいと思いました。

メモの魔力 The Magic of Memos (NewsPicks Book)

メモの魔力 The Magic of Memos (NewsPicks Book)

 


さて、そんな自分は普段あまりメモを取りませんし、前田さんが言われている知的生産のためのメモという行為は尚更できていません。なので本書は全く耳の痛い内容で、アンテナ張ってキャッチしたらそれを自分なりにちゃんと分析していく姿勢にシフトしていきたいと思わせられます。自分に足りないのは物事の本質的なところを考える部分だと痛感することが多く、身近で尊敬している人はみな本質的なところを話すんですよね。。

で、そんな知的生産のためのメモについては今回は抜きにして「ただ事実を記録に残す」という行為でのメモについて普段から思うところがあるので、この機に記事にしておきたいと思いました。前田さんも「知的生産に結び付けないとあまり意味が無い」「単に記録するだけなら機械に任せたら良い」と言われている部分、それもただ書き写すという行為そのものについてです。

自分の場合、普段あまりメモを取らないのですが、唯一、セミナーと会議に関してのみは「喋った内容とスクリーンに映し出された内容を全てメモしてやる!」という気持ちでノートPCでメモしています。

おかげで完全に独自の運指ではありますがブラインドタッチができるようになってきており(数字と記号の列はまだ全然ダメですが)、徐々にタイピング速度も上がってきています。

ただそれでもかなりメモを取りこぼしていて、しかもタイプすることに集中していると今しゃべっている内容に追いつかない時にまるまる聞き逃して、話を断片的にしか聞けていない状態になり話を理解できなくなるという本末転倒なことが多々あります。重要な部分をうまく要約して書いていけたら良いのでしょうけれど。。

ちなみに、実は以前はメモ帳に手書きでメモしていました。

例えばCEDECで受講したセッションはスライドの絵も気になるものは書き写したりしつつ書いていたのですが、自分の場合は人に共有する前提なので手書きのメモを後からデジタルに起こす作業が苦痛でノートPCに変えました。
ポメラとか携帯性に優れたデバイスも検討したのですが結局ノートPC

前田さんは手書きでのメモを勧められているため「むむむ‥」と葛藤な感じでもあります。

ただ、ノートPCでメモしていると日本語は圧倒的に不利だと日々痛感させられます。というのも、日本語をキーボードでタイプする際に「変換」という行為が挟まるからです。

具体的には次の3つの変換です。

 ① 正しい漢字への変換

 ② カタカナへの変換

 ③ 英語への変換

まず ① ですが、全てひらがなでタイプすれば写すことのみに集中できますが、非常に読み辛いメモになる上に、後から漢字に修正するのは苦痛です(機械学習等で、ひらがなの文章を適切な漢字&カタカナに一括変換させるとかできるサービスとか、探せばありますかね?あったら全てひらがなで書くということが超絶楽な速記法となり得るかも‥)。

しかし単語ごとに正しい漢字に変換していく作業はメモを取る行動を大きく阻害します。

② では、変換キーでは一発でカタカナにならない場合も多いため、1つの単語でタイプを止めてF7キーでカタカナに一括変換し、そして続きを打つ‥という面倒臭い行為が発生します。ノートPCはキーボードが小さいためF7は押す位置がズレやすいですし、ファンクションキーはホームポジションから少し離れるのでロスもあります。

③ は ② と同様にF10で変換可能ですが、空白スペースを入れて続けて英文を打っていきたい時には不便です。なので半角/全角ボタンを押して英語入力モードとかな入力モードを頻繁に切り替えてタイプすることになります。これがまた著しくメモ効率を下げているように思います。

あと手書きと比べて不利な点に、書く位置を変える際にカーソルの移動が足枷というのもあります。Home・End・PageUP・PageDownやらCtrl + 矢印キーを駆使したりマウスに持ち替えたりしてもロスなので、カーソルの移動という行為がとても煩わしく感じることが多いです。

これらの煩わしい行為が挟まれる度に、聞きとりとメモへの集中を削がれます。削がれながらもそれに抗いながらメモしていく感じになります。この状況からすごく解放されたいと思ったりします。少なくとも「ぜんぶ半角英数字でメモを取れたら、どんなに楽だろう」と。

手書きだとはこのあたりクリアされていますね。
でもパっとシェアできない。できればノートPCでメモしていきたい。

前田さんが言われているようにただ記録してシェアするだけなら、写真や音声録音などの方法があり、文字起こしもORCの精度が上がればもはや機械で全く良いのでしょうけれど‥そして自分はもっと深く掘り下げて考えることに時間を使っていかないといけないのでしょうけれど‥

とりあえず、本書の続きを読み進めてこのあたりまた考えてみたいと思いました。

ちなみに、セミナー等のメモをブログに載せる際に「なるべく自分の考えを添えるようにしなければ」とは思っていて、そういう意味ではモンハンワールドのエフェクトエディタの講演レポートは、これまで単なるメモを掲載し続けてきた中でようやくまともなレポートになったかと思います。。

ついでに前田さんが使っているというスマホアプリをペタリ。

smatu.net