本記事の内容
- 論文のグラフから値を読み取る自作アプリを作成することが目標(下図)
- Windowsフォームアプリ(C#)を使用
画像を読み込む→マウスで点をクリックしていく→画像のピクセル座標をRichTextBoxに表示させる
方法(要点まとめ)
(1) コントロールの配置と設定
1.Button, Label, TextBox, RichTextBox, Panel, PictureBoxを配置する。PanelはPictureBoxの下に配置する。Panelを使用すると、画像サイズがフォームのウィンドウサイズより大きい場合に、縦方向と横方向のスクロールバーを表示させることができる。
2. 画像がはみ出た場合にスクロールして表示させるために、PanelのAutoScrollをTrueにし、PictureBoxのSizeModeをAutoSizeにする。Visual Studioの右下に表示される各コントロールのプロパティから設定してもよいし、コードで直接入力してもよい。public Form1(){...}
のところに記述する。
// Panelのプロパティ設定
panel1.AutoScroll = true;
// PictureBoxをPanel内に追加
panel1.Controls.Add(pictureBox1);
// PictureBoxのサイズモード設定
pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
(2) マウスをクリックしたときに、座標を読み取り、点を描画する。
あらかじめ諸々の変数を定義しておく。public partial class Form1 : Form{...
の直後に入力する。
private Image originalImage;
private Image temporaryImage;
private List<Point> clickedPoints = new List<Point>();
private int dotCount = 0;
pictureBoxの重要な設定はこんな感じ
1. MouseClickイベントを使って、クリックしたらその場所の座標をclickedPointsリストに追加していく(点の描画用)。RichTextBoxにもAppendTextで現在の点を追加する。ついでにクリックした総カウント数もdotCount変数に記録していく。
2. PainイベントでclickedPointsに記録した点をプロットする。
// リスト内のすべての点に赤い円を描画
foreach (Point p in clickedPoints)
{
e.Graphics.FillEllipse(Brushes.Red, p.X - 5, p.Y - 5, 10, 10);
}
3. MouseMoveイベントで、現在のマウスの座標をラベルにリアルタイムで表示する。
label2.Text = e.Location.ToString();
コード全体
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
namespace Counter
{
public partial class Form1 : Form
{
private Image originalImage;
private Image temporaryImage;
private List<Point> clickedPoints = new List<Point>();
private int dotCount = 0;
public Form1()
{
InitializeComponent();
// Panelのプロパティ設定
panel1.AutoScroll = true;
// PictureBoxをPanel内に追加
panel1.Controls.Add(pictureBox1);
// PictureBoxのサイズモード設定
pictureBox1.SizeMode = PictureBoxSizeMode.AutoSize;
}
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
clickedPoints.Add(e.Location); // クリックされた位置をリストに追加
pictureBox1.Invalidate(); // PictureBoxを再描画
// RichTextBoxに座標を追加
Point pointforRT = e.Location;
richTextBox1.AppendText($"{pointforRT.X} {pointforRT.Y}\n");
//カウント
dotCount++;
txtBoxCount.Text = dotCount.ToString();
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
// リスト内のすべての点に赤い円を描画
foreach (Point p in clickedPoints)
{
e.Graphics.FillEllipse(Brushes.Red, p.X - 5, p.Y - 5, 10, 10);
}
}
private void btnReadImg_Click(object sender, EventArgs e)
{
using (OpenFileDialog openFileDialog = new OpenFileDialog())
{
openFileDialog.Filter = "画像ファイル(*.jpg;*.png;*.bmp;*.tif)|*.jpg;*.png;*.bmp;*.tif";
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
originalImage = Image.FromFile(openFileDialog.FileName);
temporaryImage = new Bitmap(originalImage);
pictureBox1.Image = new Bitmap(originalImage);
}
}
}
private void btnReset_Click(object sender, EventArgs e)
{
if (originalImage != null)
{
pictureBox1.Image = new Bitmap(originalImage);
}
clickedPoints.Clear(); // プロットのリストをクリア
pictureBox1.Invalidate(); // PictureBoxを再描画
richTextBox1.Clear();
txtBoxCount.Clear();
dotCount = 0;
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
label2.Text = e.Location.ToString();
}
}
}