課題の進め方
基本的には適当なプロジェクト/ソリューションを作って課題を進めた上で,MainForm.cs
を提出する.
採点はコマンドラインからdotnet new etoapp
を実行した上でMainForm.cs
を提出されたもので上書きすることにより行う.
採点者は基本的に採点者自身の環境で動作確認を行うことに注意する.
第6回課題においてMainForm.cs
以外に提出に含めたいものがある場合(たとえば画像ファイル等)は事前にメール(メールアドレスはClassroom内「受講者用案内」を参照)で相談のこと.
他の人(受講者・非受講者両方)に解答内容(一部でも)を見せない,そして他の人の解答内容(一部でも)を見ないようお願いします.特に, 公開の場所に解答を置かないようお願いします.githubやbitbucket等は使える人は使えばよいと思いますが,privateレポジトリにするようにお願いします.
プロジェクト/ソリューションの作成
Note
再掲:プロジェクトは一つの実行形式やライブラリを作成するためのコード等を全てまとめたものであり,ソリューションは関連するプロジェクトをまとめたもの(参考:What are solutions and projects in Visual Studio?).
指定された名前(課題5ではQ5
,課題6ではQ6
とする)の空のフォルダを適当な場所に新規作成し,
VSCodeで作成したフォルダを開く.そして,VSCode内のターミナルで以下を実行する.
dotnet new etoapp -sln
課題の実施
MainForm.cs
を問題文の指示の通りに編集する(提出・採点手続きの簡略化のため提出する.csファイルは一つのみ).作成した.csファイルには先頭部分に学籍番号と名前をコメントとして含めること.また,自身のプログラムの動作確認を行ったプラットフォームの情報(Mac, Gtk, Wpfの別.複数可.わからないならOS名)も含めるものとする.こちらの情報はあくまで念のためであり,基本的には採点者は自身の環境で動作を確認を行う.なので,たとえば学籍番号Z0TB9999の東北 大学さんの提出ファイルは,もし当人が動作確認をを用いて行ったのであれば .Mac
// Z0TB9999
// 東北 大学
// 動作確認:Mac
という行から始まる.
提出
できあがった MainForm.cs
をClassroom内の当該回の「課題」より提出する.また問題文に指示がある場合はそのファイル(例:課題6で提出物に含めたいリソースがある場合)も提出する.提出前には以下を確認しよう.
- 提出プログラムコードのファイル名は
MainForm.cs
になっているか - 提出するファイルに学籍番号と名前がコメントとして含まれているか
- 文献やWebサイトを参考にした場合は文献の情報やURLおよびアクセス日に加えて元文献のどの部分を参考にしたのかがコードの当該箇所付近のコメントとして記述されているか
- 友人と相談した・された場合はその友人の名前および大雑把な相談の内容がコメントとして書かれているか
- ただし,友人の解答を見ない,そして友人に解答を見せないようお願いします
- TA・教員と相談した場合は,その旨と大雑把な相談の内容がコメントとして書かれているか
基本課題
その1
ラベルを
Label
ボタンを
(Button)
テキストボックスを
[ ]
テキストエリアを
+-------------+
| |
| |
+-------------+
というアスキーアートとして図示することにする.
このとき,Eto.Formsを用いて以下のようにコントロールが配置されているウィンドウを作成しなさい. ただし,テンプレートから生成されたコードのうち,MainForm.cs のみ変更すること.
File: [ ] (Load)
+-------------------------------------+
| |
| |
| |
| |
| |
+-------------------------------------+
Ready
ただし,以下を満たすこと.
- "File:","Ready"の部分は
Label
を用いて実現 - "File:" の右のテキストボックスは
TextBox
を用いて実現 - "(Load)"の部分は
Button
を用いて実現 - 中央のテキストエリアは
TextArea
を用いて実現 - ウィンドウのサイズは十分に大きい(たとえば400x300程)
- TextBoxの部分にはプレースホルダーテキストを設定してもよいし,しなくてもよい
PlaceholderText
プロパティ(string
型)を用いると設定できる.
- ウィンドウサイズの変更に伴い,TextBoxの部分の幅,TextAreaの部分の高さと幅が伸長するように
その2
便宜上,上記で"Ready"と書かれている部分を「ステータス行」と呼ぶことにする.
上記のアプリケーションに以下の機能を実装せよ.
- "Load"ボタンが押されたら,テキストボックスに入力されたパスにあるファイルがもし存在していれば開き,その内容を中央のテキストエリアに表示する.
- 読み込みに成功したら,ステータス行に"Load ok"と表示する.
- ファイルが存在していなければ,その旨をステータス行に表示する.
- 本課題では,ファイルを開いたり読みこんだりしたときに例外が発生した場合の挙動については規定しない.
ただし,相対パスを用いて「ドキュメント」内(Windowsの場合.Windows 8以前は「マイ ドキュメント」)や「書類」(~/Documents
)内(Mac等の場合で.NET 8以降.7以前はホームディレクトリ.以降の説明は.NET 8以降を想定)のファイルを開けるようにするために,以下をMainForm
のコンストラクタに含めるなどせよ(フォームの関心毎ではないのでMain
等で実行すべきだが,3箇所のファイルを修正するのは大変なので).
// 現在の(作業)ディレクトリを,プラットフォーム毎の「ドキュメント」的なディレクトリに設定する
// Windowsだと「ドキュメント」,Macで.NET 8以降だと「書類」(~/Documents/),7以前はホームディレクトリ.他の環境は未確認.
//
// より安全には,Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) が空文字列かどうか
// を検査してから Environment.CurrentDirectory に代入したほうがよい.
.CurrentDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); Environment
上記の設定により,「ドキュメント」フォルダ(Windowsの場合)や「書類」(Macの場合)フォルダの直下のファイルにファイル名のみでアクセスできるようになる(より正確には相対パスの基準がこれらのフォルダになる).より具体的には:
Windows 10/11であれば,「ドキュメント」(エクスプローラーの左サイドバーの「クイックアクセス」か「PC」以下から見付かるはず)フォルダ直下に
test.txt
を適当な内容で用意し,作成するアプリケーションのテキストボックスにtest.txt
を入力して"Load"ボタンを押せばその内容が表示されるようになる.Macであれば,Finderの左サイドバーの「よく使う項目」の「書類」(
~/Documents
)直下にtest.txt
を適当な内容で用意し,作成するアプリケーションのテキストボックスにtest.txt
を入力して"Load"ボタンを押せばその内容が表示されるようになる.
Tip
ファイルを置く場所を確認してみるには以下を実行してみるのもよい.
.WriteLine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)); Console
当方の環境(Mac)では以下が表示される.
/Users/kztk/Documents
当該パスはホームディレクトリを表す~
を用いて書くと~/Documents/
.
Caution
Mac含めUnix環境では.NET 8以降とそれ以前で挙動が異なるので注意(参考:https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/8.0/getfolderpath-unix)
Tip
ファイルが存在するかどうかを確認するには File
クラスの static メソッド Exists(string)
を利用する.より具体的には,File.Exists(path)
は path
が有効なパスで,指す先にファイルが存在しているときに,true
を返し,そうでないときにはfalse
を返す.(指す先に存在しているのがディレクトリであるときもfalse
となることに注意する.)
Note
なお,File.Exists(path)
が true
を返した場合にも,ファイルの読み取りが行えない場合はある.たとえば,当該ファイルの read パーミッション がない場合にはUnauthorizedAccessException
が発生する.
発展課題
Important
本課題を完了できたのならば本課題の解答のみを提出すればよく,基本課題の解答は提出する必要はない.
上記アプリケーションを拡張し,"Save"ボタンを追加せよ.コントロールの配置は以下のようにせよ.
File: [ ] (Load) (Save)
+-------------------------------------+
| |
| |
| |
| |
| |
+-------------------------------------+
Ready
"Save"ボタンが押されたときには,その時点でのテキストエリアの内容を,その時点でのテキストボックスに入力されたパスのファイルとして保存する機能を実装せよ.ただし,
もしファイルが見付からなければそのファイルを作成するようにし,ファイルが見付かったならばそのファイルを上書きするようにする.
何らかの理由で与えられたパスのファイルを作成したり開いたりできない場合は,ステータス行に読込や保存に失敗した旨を表示
書き込みに成功したら,ステータス行に"Save ok"と表示する
Tip
File.WriteAllText
を実行し,適当な例外処理をしたので十分.どんな例外が発生しうるかは,
当該メソッドのリファレンスを参照.
もっと親切なエラーメッセージをステータス行に表示したい場合は
File.Exists
や Directory.Exists
や,File.GetAttributes
などを利用するとよいかもしれない(参考:.NET API リファレンスのFlieクラスの説明)
注意(2022-05-25追記):どうやらWindows環境(.NET 5.0.408,6.0.201で確認)では,ArgumentException
やPathTooLongException
が上記リファレンスの記述通りには発生しない模様.また,FileInfo
のコンストラクタも記述通りの例外を投げない模様.たとえば,fi = new FileInfo("./test???.txt")
は例外を投げず,fi.CreateText()
などとしたときにIOException
が発生する.