为什么我的应用程序不能绘制任

时间:2016-08-14 12:50:53

标签: c#

我很新(阅读3周exp)到C#(一般编程),用html / css和javascript开始,现在用C#开始了。

我正试图在Windows窗体中创建自己的简单'Paint'应用程序。但我遇到了一个问题,只是无法绕过它,不管我读了多少或跟随其他人的代码,我都被卡住了。以下代码工作正常,但在调整应用程序窗口大小时,绘图会消失。

作为一个解决方案,我已经阅读了在panel1_Paint事件中声明Graphics方法,这应该得到解决。这是我的问题。看到最后一个代码示例,我想出了这个(是的,就像我说的,我是新手)并且它没有绘制任何东西。

我只是试图在panel1_Paint事件下重新创建第一个例子,但我想在mouseMove事件期间出现了问题,我无法弄清楚它是什么。

有人可以向我解释我在这里缺少什么,非常感谢。提前谢谢。

[旧代码]

namespace Painter
{
public partial class Form1 : Form
{
    Graphics graphics;
    Pen pen = new Pen(Color.Black, 1);
    Point startingPoint = new Point(0, 0);
    Point endPoint = new Point(0, 0);
    bool mousePaint = false;



    public Form1()
    {
        InitializeComponent();
        this.DoubleBuffered = true;

    }

    private void panel1_MouseDown(object sender, MouseEventArgs e)
    {
        startingPoint = e.Location;
        if (e.Button == MouseButtons.Left)
        {
            mousePaint = true;
        }
    }

    private void panel1_MouseMove(object sender, MouseEventArgs e)
    {
        if(mousePaint == true)
        {
            endPoint = e.Location;
            graphics = panel1.CreateGraphics();
            graphics.DrawLine(pen, startingPoint, endPoint);
        }
        startingPoint = endPoint;
    }

    private void panel1_MouseUp(object sender, MouseEventArgs e)
    {
        mousePaint = false;
    }


  }
}

[新规范]

namespace Painter
{
public partial class Form1 : Form
{
    Pen pen = new Pen(Color.Black, 1);
    Point startingPoint = new Point(0, 0);
    Point endPoint = new Point(0, 0);
    bool mousePaint = false;



    public Form1()
    {
        InitializeComponent();
        this.DoubleBuffered = true;

    }

    private void panel1_Paint(object sender, PaintEventArgs e)
    {
        Graphics graphics = panel1.CreateGraphics();

        if (mousePaint == true)
        {
            graphics.DrawLine(pen, startingPoint, endPoint);
        }
    }


    private void panel1_MouseDown(object sender, MouseEventArgs e)
    {
        startingPoint = e.Location;
        if (e.Button == MouseButtons.Left)
        {
            mousePaint = true;
        }
    }

    private void panel1_MouseMove(object sender, MouseEventArgs e)
    {
        if(mousePaint == true)
        {
            endPoint = e.Location;
        }
        startingPoint = endPoint;
    }

    private void panel1_MouseUp(object sender, MouseEventArgs e)
    {
        mousePaint = false;
    }


   }
 }

2 个答案:

答案 0 :(得分:1)

  

以下代码可以正常工作,但在调整应用程序窗口大小时,绘图会消失。

这是因为调整应用程序窗口的大小会使面板的一部分无效,从而导致重绘部分。

第二种方法不起作用的原因(标记为 [新代码] 的原因)是因为只有在重绘相关组件时才会调用 Paint 事件。您可以通过在 MouseDown / MouseMove 事件处理程序中强制重绘面板来部分解决此问题,但您仍然会丢失以前绘制的内容。

可能的解决方案是创建 Bitmap 的实例并在那里进行绘制。然后将此位图设置为面板的 BackgroundImage 。您可以找到有关该here的更多信息。当然,如果应用程序窗口缩小或放大,您需要考虑调整大小以及位图应该发生的事情。

以下是我快速整理的一些代码,以帮助您入门:

namespace WinForms_PaintTest
{
    public partial class Form1 : Form
    {
        private Pen pen;
        private Bitmap bitmap;

        public Form1()
        {
            InitializeComponent();
            this.pen = new Pen(Color.Black, 1);
            this.bitmap = new Bitmap(this.panel1.Width, this.panel1.Height);
            this.panel1.BackgroundImage = this.bitmap;
        }

        private void panel1_MouseMove(Object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                using (Graphics g = Graphics.FromImage(this.bitmap))
                {
                    g.DrawRectangle(this.pen, e.Location.X, e.Location.Y, 1, 1);
                }
                this.panel1.Refresh();
            }
        }

        private void Form1_FormClosed(Object sender, FormClosedEventArgs e)
        {
            this.pen.Dispose();
            this.bitmap.Dispose();
        }
    }
}

同样关于此:

this.DoubleBuffered = true;

我相信你的意图是在重新绘制相关控件时防止闪烁?如果是这种情况,您需要针对面板设置此属性,而不是针对表单本身。这有点棘手但因为面板的 DoubleBuffered 属性是受保护的所以你需要从面板继承或诉诸于反射。您可以找到更多信息here

答案 1 :(得分:1)

private void panel1_Paint(object sender, PaintEventArgs e)
{
    Graphics graphics = panel1.CreateGraphics();

这是胡说八道!始终只使用e.Graphics param中的Paint对象!

另外:要触发Paint事件,只要您的绘图数据发生变化,请执行panel1.Invalidate();

另外:确保你明白你的mousePaint旗帜应该控制什么:鼠标绘画(即添加新的形状来绘制)或常规绘画(即以前绘制的所有形状)!?请注意,所有绘图,当前和之前的需要在Paint事件中完成,必要时,即一遍又一遍!

能够这样做:收集所有的shpes&#39; List<T> ..

中的数据

Doublebuffer Panel,您需要将其子类化。您的代码会为DoubleBuffering启用Form,这很好但不会帮助Panel ..

而是简单地使用PictureBox,这是用于绘图的控件!

DoubleBuffered Panel 子类就像这样简单:

class DrawPanel : Panel 
{
   public DrawPanel()
    {
        DoubleBuffered = true;
    }
}