绘制在两个pictureBoxes

时间:2018-05-22 10:44:23

标签: c# windows winforms events picturebox

我在Windows窗体应用程序上创建了两个pictureBoxes。我想使用FillEllipse()绘制它们,但由于某种原因我只能在第一个pictureBox中绘制。我相信问题是我不能正确理解事件的运作方式。这是代码:

public Form1()
    {
        InitializeComponent();
        pictureBox1.Paint += new PaintEventHandler(this.pictureBox1_Paint);
        pictureBox2.Paint += new PaintEventHandler(this.pictureBox2_Paint);
    }

    private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        Graphics gr = e.Graphics;
        Point p1 = pictureBox1.Location;
        gr.FillEllipse(new SolidBrush(Color.Red), new Rectangle(p1.X + 40, p1.Y + 40, 20, 20));
        gr.FillEllipse(new SolidBrush(Color.Red), new Rectangle(p1.X + 40, p1.Y + 80, 20, 20));
        gr.FillEllipse(new SolidBrush(Color.Red), new Rectangle(p1.X + 80, p1.Y + 40, 20, 20));
        gr.FillEllipse(new SolidBrush(Color.Red), new Rectangle(p1.X + 80, p1.Y + 80, 20, 20));
    }

    private void pictureBox2_Paint(object sender, PaintEventArgs e)
    {
        Graphics br = e.Graphics;
        Point p2 = pictureBox2.Location;
        br.FillEllipse(new SolidBrush(Color.Red), new Rectangle(p2.X + 40, p2.Y + 40, 20, 20));
        br.FillEllipse(new SolidBrush(Color.Red), new Rectangle(p2.X + 40, p2.Y + 80, 20, 20));
        br.FillEllipse(new SolidBrush(Color.Red), new Rectangle(p2.X + 80, p2.Y + 40, 20, 20));
        br.FillEllipse(new SolidBrush(Color.Red), new Rectangle(p2.X + 80, p2.Y + 80, 20, 20));
    }

3 个答案:

答案 0 :(得分:2)

您正在绘制pictureBox2。您的问题是您正在视口之外绘图,因为您正在绘制图片框2在表单上的位置,但是在图片框中。 paypal Amount Total mismatch 给出了表单上方框的位置。如果此框位于x = 240,y = 240的位置,则表示您正在这些位置的框内绘图。如果你的盒子只有w = 50,h = 50,你就不会看到你画的是什么,因为它在右边和底部都是等待的

答案 1 :(得分:0)

所以,这是非常低效的,你将所有东西都画了两次,导致负荷增加一倍。你需要做的是在位图中绘制一次并将位图加载到两个图片框中。

https://docs.microsoft.com/en-us/dotnet/framework/winforms/advanced/how-to-create-a-bitmap-at-run-time

但是,如果使用位图不会让您实现您尝试做的任何事情,请编写自定义控件。虽然这不会提高性能,但它至少会阻止代码重复。

https://docs.microsoft.com/en-us/dotnet/framework/winforms/controls/creating-a-wf-control-design-time-features

Bitmap img= new Bitmap(100, 100);
Point p1 = pictureBox1.Location;
Graphics gr = Graphics.FromImage(img);
gr.FillEllipse(new SolidBrush(Color.Red), new Rectangle(p1.X + 40, p1.Y + 40, 20, 20));
gr.FillEllipse(new SolidBrush(Color.Red), new Rectangle(p1.X + 40, p1.Y + 80, 20, 20));
gr.FillEllipse(new SolidBrush(Color.Red), new Rectangle(p1.X + 80, p1.Y + 40, 20, 20));


picturebox1.Image = img;
picturebox2.Image = img;

答案 2 :(得分:0)

PaintEventArgs e.Graphics为您提供了一个控件DeviceContext(认为它是对控件图形表面的引用)和一组可用于在该上下文上执行图形操作。

使用e.Graphics时,所有绘图都出现在图形对象引用的基础曲面内(在这种情况下为PictureBox ClipRectangle)。所有坐标都与此区域相关点。

因此,您只需使用控件的客户端区域作为唯一参考来指定图形的位置和大小。绘图区域尺寸也由e.Graphics.ClipBounds(以PageUnits表示)和控件ClientRectangle属性(以Pixels表示)报告。
ClientRectangle是控件的一个区域,它排除非客户元素,例如BordersMenusScrollBarsTitleBar等;它"内在"。

然而,客户区定义可以根据控件的内部结构进行更改(例如,设想ListViewComboBox控件。)

每次控件需要重新绘制时,都会引发控件的Paint()事件 首次创建控件后,它总是会被提升 之后,例如,当控件由于某些原因而被触发时,它可以被触发"模糊"通过另一个控件/窗口或当包含它的Form最小化时。

可以手动提升"调用控件的Invalidate()方法 这可能是强制控件重新绘制自身的首选方法,因为Invalidate()方法允许指定需要重新绘制的控件的已定义部分(RectangleRegion),限制绘画到这个区域。

您可以这样修改代码:

public Form1()
{
    InitializeComponent();
    pictureBox1.Paint += new PaintEventHandler(this.pictureBox1_Paint);
    pictureBox2.Paint += new PaintEventHandler(this.pictureBox2_Paint);
}

private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
    e.Graphics.FillEllipse(Brushes.Red, new Rectangle(40, 40, 20, 20));
    e.Graphics.FillEllipse(Brushes.Red, new Rectangle(40, 80, 20, 20));
    e.Graphics.FillEllipse(Brushes.Red, new Rectangle(80, 40, 20, 20));
    e.Graphics.FillEllipse(Brushes.Red, new Rectangle(80, 80, 20, 20));
}

private void pictureBox2_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
    e.Graphics.FillEllipse(Brushes.Red, new Rectangle(40, 40, 20, 20));
    e.Graphics.FillEllipse(Brushes.Red, new Rectangle(40, 80, 20, 20));
    e.Graphics.FillEllipse(Brushes.Red, new Rectangle(80, 40, 20, 20));
    e.Graphics.FillEllipse(Brushes.Red, new Rectangle(80, 80, 20, 20));
}

SmoothingMode = SmoothingMode.AntiAlias用于"美化"图形结果。
这将产生更平滑的边界。

使用的Drawing Brush是一个库存对象(系统提供),不需要Disposed()
如果您使用其中一个创建Brush与画笔相关的类,必须处理您创建的对象。

using (SolidBrush brush = new SolidBrush(Color.Red))
{
    e.Graphics.FillEllipse(brush, new Rectangle(40, 40, 20, 20));
}