2

線を描くための描画パネルとボタンを備えたC#のWindowsフォームアプリケーションがあります。

ボタンをクリックすると、ランダムな2点の線を引くことができます。

Pen p = new Pen(Color.Black, 5);
//point for start 
Point ps = new Point();
//point for end 
Point pe = new Point();

private void drawPanel_MouseDown(object sender, MouseEventArgs e)
{
  ps.X = e.X;
  ps.Y = e.Y;
  pe = ps;
}

private void drawPanel_MouseMove(object sender, MouseEventArgs e)
{
  // when button is clicked for drawing draw = true;
  if (draw)
  {
    if (e.Button == MouseButtons.Left)
    { 
      pe = new Point(e.X, e.Y);
    }
  }
}

private void drawPanel_MouseUp(object sender, MouseEventArgs e)
{
  onMouseUpFlag = true;
}

private void drawPanel_Paint(object sender, PaintEventArgs e)
{
  Graphics g = drawPanel.CreateGraphics();
  if (onMouseUpFlag)
  {
    g.DrawLine(p, ps, pe); 
    g.Dispose(); 
  }
} 

プログラムにはいくつかの欠陥があります:

  • 線を引くと、メインウィンドウがどこかに移動した場合にのみ表示されます(通常は非表示にした場合)
  • 1本の線しか描くことができません。

これらのバグを修正する方法について何か提案はありますか?

編集

私はあなたの答えを読み、いくつかの変更を加えました:

Pen p = new Pen(Color.Black, 5); 
Point ps = new Point();
Point pe = new Point();

List<Point> linesStart= new List<Point>();
List<Point> linesEnd= new List<Point>();

private void drawPanel_MouseDown(object sender, MouseEventArgs e)
{
  ps.X = e.X;
  ps.Y = e.Y;

  linesStart.Add(ps);

  pe = ps;
}

private void drawPanel_MouseMove(object sender, MouseEventArgs e)
{
  if (e.Button == MouseButtons.Left)
  {
    pe = new Point(e.X, e.Y);

    //adding end point .. actually adds a lot of points 
    linesEnd.Add(pe);
  }
}

bool onMouseUpFlag = false;

private void drawPanel_MouseUp(object sender, MouseEventArgs e)
{
  onMouseUpFlag = true;
  drawPanel.Invalidate();
}

private void drawPanel_Paint(object sender, PaintEventArgs e)
{ 
  if (onMouseUpFlag)
  {
    for (int i = 0; i < linesStart.Count; i++)
    {
      e.Graphics.DrawLine(p, linesStart[i], linesEnd[i]);
    } 
  }
} 

現在、複数の線のDrawLineを修正しようとしています。ペイントイベントは複数行を実行できますが、開始点のみが問題ありません。どういうわけか、エンドポイントはあまり正しくありません。MouseMoveイベントの最後のポイントを正確に設定できる場所はどこですか?

4

3 に答える 3

3

パネルでInvalidateメソッドを呼び出す必要があります。

private void drawPanel_MouseUp(object sender, MouseEventArgs e)
{
  onMouseUpFlag = true;
  drawPanel.Invalidate();
}

また、PaintEventのGraphicオブジェクトを使用します。

private void drawPanel_Paint(object sender, PaintEventArgs e)
{
  if (onMouseUpFlag)
  {
    e.Graphics.DrawLine(p, ps, pe); 
  }
} 

複数の行の場合、コレクションオブジェクトにポイントを保持する必要があります。

更新されたコードごとに、これがあなたがやろうとしていると私が思うことの実際的な例です:

private class Line {
  public Point Starting { get; set; }
  public Point Ending { get; set; }

  public Line(Point starting, Point ending) {
    this.Starting = starting;
    this.Ending = ending;
  }
}
List<Line> lines = new List<Line>();

private Point downPoint = Point.Empty;
private Point movePoint = Point.Empty;
private bool movingLine = false;

public Form1() {
  InitializeComponent();

  panel1.Paint += panel1_Paint;
  panel1.MouseDown += panel1_MouseDown;
  panel1.MouseMove += panel1_MouseMove;
  panel1.MouseUp += panel1_MouseUp;
}

void panel1_MouseDown(object sender, MouseEventArgs e) {
  if (e.Button == MouseButtons.Left) {
    downPoint = e.Location;
  }
}

void panel1_MouseMove(object sender, MouseEventArgs e) {
  if (e.Button == MouseButtons.Left) {
    movingLine = true;
    movePoint = e.Location;
    panel1.Invalidate();
  }
}

void panel1_MouseUp(object sender, MouseEventArgs e) {
  if (e.Button == MouseButtons.Left) {
    movingLine = false;
    lines.Add(new Line(downPoint, e.Location));
    panel1.Invalidate();
  }
}

void panel1_Paint(object sender, PaintEventArgs e) {
  e.Graphics.Clear(Color.White);
  foreach (Line l in lines) {
    e.Graphics.DrawLine(Pens.Black, l.Starting, l.Ending);
  }

  if (movingLine) {
    e.Graphics.DrawLine(Pens.Black, downPoint, movePoint);
  }

}

ちらつきを避けるために、継承されたパネルを使用してDoubleBufferプロパティをオンにします。

于 2012-10-29T20:28:36.677 に答える
1

(コード内で)再描画する場合は常に、panelinvalidateを呼び出す必要がありますdrawPanel.Invalidate()

マウスの移動が終了したら、ボタンを離します

private void drawPanel_MouseUp(object sender, MouseEventArgs e)
{
            onMouseUpFlag = true;
            drawPanel.Invalidate();
}

そして最後に、drawPanel_Paintでこのコードをあなたのコードの代わりに使用することをお勧めします。新しいグラフィックを作成するのではなく、EventArgsによって提供されるグラフィックを使用する必要があります。

private void drawPanel_Paint(object sender, PaintEventArgs e)
{
            if (onMouseUpFlag)
            {
                  e.Graphics.DrawLine(p, ps, pe); 
            }
}
于 2012-10-29T20:29:25.727 に答える
1
  1. マウスを離した後、再描画イベントをトリガーする必要があります。呼び出すだけdrawPanel.Invalidate()で、フォームが再描画されます。

  2. 複数の線を描くには、それぞれの情報をリストなどに保存し、塗り直しで各線を描く必要があります。Paintメソッドは基本的に毎回空白から開始するため、現在設定されている方法で最新のもののみを描画します。

于 2012-10-29T20:32:00.423 に答える