| ■103805 / ) |
Re[11]: Visual Basicで簡易CADを作成 |
□投稿者/ 魔界の仮面弁士 (3877回)-(2025/08/03(Sun) 11:50:26)
|
■No103802 (shiro さん) に返信 > 図形の削除はPolygonではないので、紹介して頂いたような方法では出来ないのでしょうか。
えぇと…。No103791 の >> 選択された図形を管理できるようになっているのですが、その List(Of ) コレクションから >> 不要な図形を RemoveAt (あるいは Remove) すれば、その図形を削除できることになります。 については理解されている、という事でよろしいでしょうか。 RemoveAt と Remove の違いについても、説明しなくて大丈夫ですね?
まず、『配置済みのすべての【矩形】情報』は、VB 中学校でいうところの 「Private polygons As New List(Of Polygon)」でしたよね。
shiro さんのケースでは、 『配置済みのすべての【柱】情報』が「Private snappedRectangles As New List(Of Rectangle)」 『配置済みのすべての【壁】情報』が「Private pointList As New List(Of Point)」 なわけですよね。ここまで理解いただけていると思います。
つまり、図形を保持しているのは、いずれも「List(Of 型パラメータ) クラス」です。
柱が3本立っていた場合、 柱A = snappedRectangles(0) 柱B = snappedRectangles(1) 柱C = snappedRectangles(2) なわけですが、このうち、柱Bを削除したければ、 snappedRectangles.RemoveAt(1) を呼び出せばよいことになります。これにより、残った柱は 柱A = snappedRectangles(0) 柱C = snappedRectangles(1) と変化します。
削除するごとにインデックス番号がズレますので、もしも複数の要素をまとめて削除する場合は For ループは 0 から最終番号に向けて昇順列挙しながら RemoveAt するのではなく、 For ループを最終番号から 0 にむけて降順列挙しながら RemoveAt するようにします。 No103794 のコードもそうなっていますよね?
削除部の手順は、上記の通りさほど難しくもありませんし、既に回答済みでもあります。 問題となるのは、その柱Bを「どうやってユーザーに選択させるか」という点でしょうか?
No103794 では、削除対象のオブジェクトを選択させる手段について >> ダブルクリックで削除する方式では操作しにくいという場合は、別途、削除ボタンを用意し、 >> それを押したときに IsSelected = True なものを取り除く方式にしても良いでしょう。 >> あるいは、右クリックやコンテキストメニューなどで指示する手法を採用することもできますね。 という素案を述べています。
実際、VB中学校のサンプルをダブルクリックで削除する方法だと、 複数の矩形が重なりあっている場合、重なっている部分をダブルクリックすると 手前側の矩形が削除された瞬間、奥の矩形が選択状態になってしまい、使いにくいかと思います。
たとえば、Excel の図形の場合を考えてみましょう。 Excel のワークシート上に、矩形や楕円や直線やテキストボックスなどを、適当に 5 つほど貼り付けたうえで [ホーム]リボン > [編集] グループにある[検索と選択]>[オブジェクトの選択と表示] もしくは [ページ レイアウト]リボン > [配置] グループにある、[オブジェクトの選択と表示] を選択してみます。 https://hamachan.info/win10/office/object.html
そうすると、シート上に貼った画像アイテム群が列挙され、それを使って選択することができますよね。
これと同じものを作ることは、さほど難しくは無いでしょう。
たとえば、柱の一覧を扱うための ListBox を用意しておき、 snappedRectangles.Add する際には、それと同時に、柱用の ListBox にも .Items.Add しておくのです。 Add する内容は、それぞれの柱を識別できる情報になっていれば、ひとまずなんでも良いです。 "柱1"、"柱2" といった連番情報でも良いですし、 柱のグリッド行列番号でも良いですし、 柱の Rectangle を .ToString() した座標情報でも良いです。
そのうえで、ユーザーは ListBox から削除したい柱を選択してもらいます。
snappedRectangles と ListBox のアイテム番号を常に同期させてておくことで、 ListBox の .SelectedIndex プロパティから「消したい柱のインデックス」が得られますので、 それを snappedRectangles と ListBox の両方から RemoveAt すればよいのです。
これは、複数の柱をまとめて削除したい場合にも使えます。 Do Until ListBox1.SelectedIndex = -1 snappedRectangles.RemoveAt(ListBox1.SelectedIndex) ListBox1.Items.RemoveAt(ListBox1.SelectedIndex) Loop
あるいは ListBox に頼らず、描画済みの壁や柱を直接クリックして選択させたり、 周囲の背景をドラッグして囲むことで範囲内の図形を選択状態にするといった ユーザーインターフェイスにしてもよいでしょう。
その場合、選択中のアイテムは色を変えて表現するなどの必要があるでしょうから、 Paint イベントで色を変えて描画するために、各アイテムが「選択中かどうか」を 管理するための変数が必要になってきます。これについては、現状の Private snappedRectangles As New List(Of Rectangle)() Private pointList As New List(Of Point)() だけでは、それぞれのアイテムの「位置とサイズ」しか分からず、「選択状態かどうか」を管理できません。
上記の ListBox のように、「選択されているアイテムの番号」を別管理する方法でも良いですが、 お奨めされるのは、先に何度も提案している通り、「柱クラス」や「壁クラス」を自作して、 それぞれのクラスに、座標情報だけでなく VB中学校の例のような「IsSelected プロパティ」を設けることです。
> また、計算結果はCSVやtxt形式で出力させますが、簡易CADで作成した情報を、 > ファイルで保存や読み込みをして修正・追加入力をする機能も付与したいのですが、 > この場合の保存方法は一般的にどうするのが妥当でしょうか。
ファイルの読み書きの方法が分からない、ということでしょうか。 その場合、まずは読み書きの方法を習得することから始めましょう。 それを CAD に組み込むのはその後の話になりますね。
ファイルの読み書きの基礎となるのは、System.IO 名前空間のクラス群です。 たとえば、ファイル全体を一括読み取りするなら、System.IO.File.ReadAllLines など。
データ量が多い場合は、全体をまとめて読み取るとメモリ消費量が増えてしまうため、 一行ずつ読み取って順次変換していく方法が採用されることもあります。
ファイル操作については、ひとまず、この辺りを参考にしてみださい。 http://rucio.o.oo7.jp/main/dotnet/shokyu/standard30.htm https://dobon.net/vb/dotnet/file/index.html
そのうえで、ファイルを扱う際の注意点を幾つか:
・読み書きするファイルのパスは固定にするのか、任意のパスにするのか?
任意のパスにするなら、ユーザーにパスを選択させるための OpenFileDialog / SaveFileDialog の使い方を学んだ方が良いです。
固定とする場合、そのパスは「読み書き可能な場所」でなければなりませんが。EXE と同じフォルダ―にあるファイルは 読み込みはできても書き込みや編集が許可されていないこと(例:Program Files フォルダー)が少なからずあるため、 %LocalAppData% 、デスクトップ、ドキュメント フォルダーなどの、読み書き可能なパスが使われたりします。
これらの特殊フォルダーのパスは、Environment.GetFolderPath メソッドや My.Computer.FileSystem.SpecialDirectories などから得られます。
・例外処理の方法は習得済みか?
ファイルを保存しようとしたら、ディスク容量不足や書き込み権限不足でエラーになることがあります。 その CSV を Excel で開いていたら、排他ロックがかかっていて上書き保存できないこともあるでしょう。 読み込みも同様に、アクセスできずにエラーになってしまう可能性がありますし、実際に読み込んでみたら 「拡張子が .csv なだけで、中身は Excel ブックだった」といった異常データの可能性もあるかもしれません。
このため、外部ファイルの読み書きを行う際には、「例外処理(Try〜Catch)」を組み込むことがほぼ必須となります。
・ファイルの文字コードは?
保存したいデータが、座標情報の数値だけならば、ASCII 形式でも良いですが、 漢字やカナなどを含めるのであれば、Shift_JIS か UTF-8 を採用するのが良いでしょう。 .NET では、デフォルトで UTF-8 が採用されますが、処理系によっては Shift_JIS の方が望まれることもあります。
ファイルを読み書きする際の文字コードの指定については、System.Text.Encoding クラスについて調べてみてください。
なお、そのファイルを読み書きするのが自アプリだけに限定される場合は、CSV といったテキストデータにせず、 独自のバイナリファイルや、ローカルデータベースファイルを採用するといった選択肢もあります。
|
|