3

私はc#で小さなペイントプログラムを実行しようとしています。これまでのところ、すべてが正常に機能しています。唯一のことは、マウスを十分に速く動かすと、実線があるはずの場所にギャップが表示されることです。ダブルバッファリングからmouse_moveイベントの間隔を短くするまで、すべてを試しました(実際には、これを行う方法が見つかりませんでした。システム上の他のプロセスにも悪いと思います^^)

ここで私を正しい方向に向けてくれませんか?パネルのペイント方法をオーバーライドしようとしましたが、これを試しても何も起こらないようです。

コードは次のとおりです。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Paint
{
    public partial class Form1 : Form
    {

        bool paint;
        SolidBrush color;
        //size of brush
        int pinselGröße;
        List<Point> pointListe;

        public Form1 ()
        {
            InitializeComponent ();
            pointListe = new List<Point>();
            paint = false;
            color = new SolidBrush ( Color.Black );
            //get brush size from combobox 
            pinselGröße = Convert.ToInt32 ( nudBrushSize.Value );
        }

        private void btnExit_Click ( object sender, EventArgs e )
        {
            this.Close ();
        }

        private void btnClear_Click ( object sender, EventArgs e )
        {
            Graphics gfx = pnlCanvas.CreateGraphics ();
            gfx.Clear ( pnlCanvas.BackColor );
        }

        private void pnlCanvas_MouseDown ( object sender, MouseEventArgs e )
        {
            paint = true;
            Graphics grfx = pnlCanvas.CreateGraphics ();
            //draw a rectangle with brush "color" and pinselGröße as the brush size
            grfx.FillRectangle ( color, e.X, e.Y, pinselGröße, pinselGröße );  
        }

        private void pnlCanvas_MouseMove ( object sender, MouseEventArgs e )
        {
            if ( paint )
            {
                //Graphics grfx = pnlCanvas.CreateGraphics();  
                ////put old position of mouse into variable
                //int altePosX = e.X;
                //int altePosY = e.Y;
                ////grfx.FillEllipse ( color, e.X, e.Y, pinselGröße, pinselGröße );
                //grfx.FillRectangle(color, e.X, e.Y, pinselGröße, pinselGröße);
                //grfx.Dispose();
                pointListe.Add(e.Location);
                pnlCanvas.Invalidate();
            }
        }

        private void pnlCanvas_Paint(PaintEventArgs e)
        {

            e.Graphics.DrawLines(new Pen(color), pointListe.ToArray());
        }

        private void pnlCanvas_MouseUp ( object sender, MouseEventArgs e )
        {
            paint = false;
        }

        private void nudBrushSize_ValueChanged ( object sender, EventArgs e )

            //when value of combobox changes, read value into brush size variable
            pinselGröße = Convert.ToInt32 ( nudBrushSize.Value );
        }

        private void cmbColor_SelectedIndexChanged ( object sender, EventArgs e )
        {            
            int index = cmbColor.SelectedIndex;
            color.Dispose ();
            switch ( index )
            {
                case 0:
                    {
                        color = new SolidBrush ( Color.Black );
                        break;
                    }
                case 1:
                    {
                        Console.WriteLine ( "Geht" );
                        color = new SolidBrush ( Color.Red );
                        break;
                    }
                case 2:
                    {
                        color = new SolidBrush ( Color.Blue );
                        break;
                    }
                case 3:
                    {
                        color = new SolidBrush ( Color.Green );
                        break;
                    }
            }
        }


    }
}

私がこのようにそれをするとき:

private void pnlCanvas_MouseMove ( object sender, MouseEventArgs e )
        {
            if ( paint )
            {
                Graphics grfx = pnlCanvas.CreateGraphics();
                ////put old position of mouse into variable
                int altePosX = e.X;
                int altePosY = e.Y;
                //grfx.FillEllipse ( color, e.X, e.Y, pinselGröße, pinselGröße );
                grfx.FillRectangle(color, e.X, e.Y, pinselGröße, pinselGröße);
                grfx.Dispose();
                //pointListe.Add(e.Location);
                //pnlCanvas.Invalidate();
            }
        }

        //private void pnlCanvas_Paint(PaintEventArgs e)
        //{
        //    Console.Write("mjsda2");
        //    e.Graphics.DrawLines(new Pen(color), pointListe.ToArray());
        //}

私はこれを手に入れます:

ここに画像の説明を入力してください

4

3 に答える 3

4

描画モードでどちらを使用するのかよくわからなかったので、ここに 2 つのバージョンを示します。

また、ペイント イベント ハンドラーのシグネチャが間違っていたため、pnlCanvas に接続されていない可能性もあります。

ペイント コードを実行するときは、(ほとんど) 呼び出す必要はありませんCreateGraphics。これは通常、「やり方が間違っている」というサインです。

これにより、点をクリックして線を引くことができます。

public partial class Form1 : Form
{

    SolidBrush color;
    List<Point> pointListe;
    Point _mousePoint;

    public Form1()
    {
        InitializeComponent();
        pointListe = new List<Point>();
        color = new SolidBrush(Color.Black);
    }

    private void btnClear_Click(object sender, EventArgs e)
    {
        pointListe.Clear();
        pnlCanvas.Invalidate();
    }

    private void pnlCanvas_MouseDown(object sender, MouseEventArgs e)
    {
        pointListe.Add(e.Location);
    }

    private void pnlCanvas_MouseMove(object sender, MouseEventArgs e)
    {
        _mousePoint = e.Location;
        pnlCanvas.Invalidate();
    }

    private void pnlCanvas_Paint(object sender, PaintEventArgs e)
    {
        if (pointListe.Count > 1)
        {
            e.Graphics.DrawLines(new Pen(color), pointListe.ToArray());
        }

        if (pointListe.Any())
        {
            e.Graphics.DrawLine(new Pen(color), pointListe.Last(), _mousePoint);
        }
    }

}

そして、これは1本の連続した線を描画します:

public partial class Form1 : Form
{

    SolidBrush color;
    List<List<Point>> _lines;
    Boolean _mouseDown;

    public Form1()
    {
        InitializeComponent();
        _lines = new List<List<Point>>();
        color = new SolidBrush(Color.Black);
        _mouseDown = false;
    }

    private void btnClear_Click(object sender, EventArgs e)
    {
        _lines.Clear();
        pnlCanvas.Invalidate();
    }

    private void pnlCanvas_MouseDown(object sender, MouseEventArgs e)
    {
        _mouseDown = true;
        _lines.Add(new List<Point>());
    }

    private void pnlCanvas_MouseMove(object sender, MouseEventArgs e)
    {
        if (_mouseDown)
        {
            _lines.Last().Add(e.Location);
            pnlCanvas.Invalidate();
        }
    }

    private void pnlCanvas_MouseUp(object sender, MouseEventArgs e)
    {
        _mouseDown = false;
    }

    private void pnlCanvas_Paint(object sender, PaintEventArgs e)
    {
        foreach (var lineSet in _lines)
        {
            if (lineSet.Count > 1)
            {
                e.Graphics.DrawLines(new Pen(color), lineSet .ToArray());
            }   
        }

    }

}
于 2012-11-09T16:48:27.127 に答える
2

Mousemove イベントはスキップされます - マウスは実際にはイベントよりも速く、アプリが追いつくことができます。その結果、ピクセルごとに 1 つずつ、マウス移動の連続ストリームが得られなくなります。

あなたがする必要があるのは、前のマウス移動で取得した前の位置を追跡し、前の位置から現在の位置まで点ではなく線を描くことです。ユーザーがマウスを非常に速く動かさない限り、これはマウスの動きを十分に近似しているため、すべてのピクセルを正確に追跡していないことに気付かないでしょう。

于 2012-11-09T16:48:10.960 に答える
2

ギャップが発生している場所は明確ではありませんが、MouseDown イベントに最初のポイントを追加すべきではありませんか? それはあなたが見ているギャップのタイプを説明できますか?

また、MouseDown イベントで四角形を塗りつぶすのはなぜですか?

それ以外の場合は、おそらくこれらのギャップがどのように見えるかのスクリーンショット.

于 2012-11-09T16:31:19.490 に答える