2012-10-29 92 views
2

我有一個Windows窗體應用程序在C#中使用繪圖面板和一個按鈕 - 繪製一條線。PaintEvent不覆蓋

單擊按鈕時,可以爲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。 Paint事件可以做多行,但只有起點沒問題。不知何故,終點不是很正確。我可以在哪裏準確設置MouseMove事件的最後一點?

+0

我更新了我的答案。請儘量避免更改問題。如果您有更多問題,請隨時將其作爲單獨問題發佈。 – LarsTech

回答

3

你必須調用面板上的Invalidate方法:

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

此外,從的paintEvent使用圖形對象:

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); 
    } 

} 

使用的inherited panel打開雙緩衝屬性,以避免閃爍。

+0

或刷新()如果像我這樣你很懶。 – LightStriker

+0

LarsTech,太棒了!感謝您的幫助 !! – Bor

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); 
      } 
} 
1
  1. 您需要的鼠標放手後觸發重繪事件。只需撥打drawPanel.Invalidate()即可重新繪製表格。

  2. 要繪製多行,您必須將每一行的信息存儲在列表或其他內容中,並在繪製每一行。Paint方法基本上每次都有一個空格開始,所以它只會繪製最近的設置方式。