C#のwinFormでpictureBoxに描画をするアプリケーションを作成しています。
例えばpictureBoxの中に四角形を描画するとして、コントロールのnumericUpDownを配置し、その値を四角形の辺の長さに指定するとします。
以下のコードは単純にpictureBoxの中央に赤い四角形を描画する例です。
C#
1namespace TestForm { 2 partial class Form1 : Form { 3 private PictureBox pictureBox1 = new PictureBox(); 4 private NumericUpDown numericUpDown1 = new NumericUpDown(); 5 6 // initialize 7 public Form1() { 8 // pictureBox1を配置 9 pictureBox1.Location = new Point(100, 0); 10 pictureBox1.Size = new Size(500, 500); 11 12 // numericUpDown1を配置 13 numericUpDown1.Location = new Point(10, 0); 14 15 InitializeComponent(); 16 } 17 18 // numericUpDown1の値を変更した場合 19 private void numericUpDown1_Changed(object sender, EventArgs e) { 20 // 辺の長さ 21 int length = Convert.ToInt32(numericUpDown1.Value); 22 23 // Bitmapを生成してpictureBox1に表示する 24 pictureBox1.Image = MakeBmp(length); 25 } 26 27 // Bitmapを生成する関数 28 private Bitmap MakeBmp(length){ 29 // pictureBox1の大きさのBitmapを作成 30 Bitmap bmp = new Bitmap(pictureBox1.Size.Width, pictureBox1.Size.Height); 31 using (Graphics g_bmp = Graphics.FromImage(bmp)) { 32 // 中央に四角形を作成 33 g_fill.FillRectangle(Brushes.Red, new Rectangle(0, 0, length, length)); 34 } 35 return bmp; 36 } 37 } 38}
実際はもっと複雑な描画を行っていますが上記のような単純な例で説明させていただきたいと思います。
このとき、numericUpDown1の値をマウスホイールで連続して値を変化させるとnumericUpDown1_Changedイベントが連続で発生します。
そうすると当然ですがBitmapの描画生成も連続して実行されるのですがこれが非常に重い処理となってしまいます。
【質問】
この重い処理をどうにかしたいと思っていますが何かよい案はないでしょうか?
また、numericUpDown1のコントロールも重くなってしまいます(連続して値が変化せず飛び飛びに値が変わってしまいます)。
考えているのは、「マウスホイールのように速い間隔で連続して値が変化しているときは、一定間隔で値を拾うようにしてBitmap生成の回数を減らす」という感じです。
この処理をどのようにすればよいのかわかりません。
もしもっと良い方法があればそちらでも構いませんのでアドバイス頂ければと思います。
【やってみたこと】
ちなみにasync/awaitで非同期処理もやってみましたが上記処理と重さは変わりませんでした。
いちおうコードを載せてみますが間違っているでしょうか?
なんとなくBitmap生成を別スレッドにしているだけでpictureBox.ImageにBitmapが格納されるのはそのスレッドが終了しないと格納されないので非同期にしても意味がないような気もします。
あと、非同期処理をしてもnumericUpDown1のコントロールが重いままなのは変わりありませんでした(なぜでしょう…?)。
c#
1namespace TestForm { 2 partial class Form1 : Form { 3 private PictureBox pictureBox1 = new PictureBox(); 4 private NumericUpDown numericUpDown1 = new NumericUpDown(); 5 6 // initialize 7 public Form1() { 8 // pictureBox1を配置 9 pictureBox1.Location = new Point(100, 0); 10 pictureBox1.Size = new Size(500, 500); 11 12 // numericUpDown1を配置 13 numericUpDown1.Location = new Point(10, 0); 14 15 InitializeComponent(); 16 } 17 18 // numericUpDown1の値を変更した場合 19 private async void numericUpDown1_Changed(object sender, EventArgs e) { 20 // 辺の長さ 21 int length = Convert.ToInt32(numericUpDown1.Value); 22 23 // Bitmapを生成してpictureBox1に表示する 24 pictureBox1.Image = await MakeBmpAsync(length); 25 } 26 27 // Bitmapを生成する関数 28 private async Task<Bitmap> MakeBmpAsync(length){ 29 // pictureBox1の大きさのBitmapを作成 30 Bitmap bmp = new Bitmap(pictureBox1.Size.Width, pictureBox1.Size.Height); 31 using (Graphics g_bmp = Graphics.FromImage(bmp)) { 32 // 中央に四角形を作成 33 g_fill.FillRectangle(Brushes.Red, new Rectangle(0, 0, length, length)); 34 } 35 return bmp; 36 } 37 } 38} 39コード
どうぞよろしくお願い致します。
【開発環境】
Windows10 + VisualStudio2015Community + .NetFramework4.5
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2016/11/08 08:45
2016/11/08 09:21
2016/11/08 11:12
退会済みユーザー
2016/11/09 09:11
2016/11/09 09:51