简体   繁体   English

在Windows.Forms中绘图

[英]Drawing in Windows.Forms

I've got a simple Windows.Forms Form. 我有一个简单的Windows.Forms表单。

I want to fill the pictureBox1 with color Color.Aqua and draw a rectangle. 我想用Color.Aqua填充pictureBox1并绘制一个矩形。

However nothing is drown untill I move the Form. 但是,在我移动表格之前,什么都不会淹没。

Why is this? 为什么是这样?

How can I force everything to be drawn without moving the Form? 如何在不移动表格的情况下强制绘制所有内容?

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private readonly Graphics _graphics;
        private List<PointF> _points;
        private Bitmap _bitmap;

        public Form1()
        {
            InitializeComponent();
            _bitmap = new Bitmap(1000, 600);
            _graphics = Graphics.FromImage(_bitmap);
            pictureBox1.Image = _bitmap;

            var timer = new Timer
            {
                Interval = 1
            };
            timer.Tick += OnTick;
            timer.Start();
            Invalidate();
        }

        private void OnTick(object sender, EventArgs e)
        {
            _graphics.Clear(Color.Aqua);
           _graphics.DrawRectangle(Pens.Black, 10, 10, 10, 10);
            Invalidate();
        }
    }
}

You must subscribe to Paint event of your picturebox and put your drawing code there,something like this: 您必须订阅图片框的Paint事件并将绘图代码放在此处,如下所示:

public Form1()
{
    InitializeComponent();
    pictureBox1.Paint += PictureBox1_Paint;
}

private void PictureBox1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.Clear(Color.Aqua);
    e.Graphics.DrawRectangle(Pens.Black, 10, 10, 10, 10);
}

This event is raised everytime the control needs to be redrawn, so you don't need that Timer trick or calling Invalidate 每次需要重绘控件时都会引发此事件,因此您不需要该Timer技巧或调用Invalidate

I see four problems: 我看到四个问题:

  1. The Invalidate() method is called for the form. 表单将调用Invalidate()方法。 This should invalidate the PictureBox, but you can do better by just invalidating the PictureBox directly. 应该会使PictureBox无效,但是您可以通过直接使PictureBox无效来做得更好。
  2. You are drawing the bitmap, but not updating the Image property of the PictureBox. 您正在绘制位图,但不更新PictureBox的Image属性。
  3. One millisecond intervals will kill you. 一毫秒的间隔会杀死您。 50 to 100 is much more reasonable, and anything less than 17 is probably faster than the refresh rate of your monitor. 50到100更为合理,任何小于17的速度都可能比显示器的刷新率更快。
  4. The whole the thing with the separate graphics is extra and not needed. 带有单独图形的整个事情是多余的,不需要的。 The pictureBox has it's own graphics context, and you do better using that. pictureBox具有其自己的图形上下文,您最好使用它。

Put it all together, and you get this: 放在一起,你会得到:

public partial class Form1 : Form
{
    private Timer _timer;
    private List<PointF> _points;

    public Form1()
    {
        InitializeComponent();

        _timer = new Timer(100);
        timer.Tick += OnTick;
        timer.Start();
    }

    private void OnTick(object sender, EventArgs e)
    {
        pictureBox1.Invalidate();
    }

    private void PictureBox1_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.Clear(Color.Aqua);
        e.Graphics.DrawRectangle(Pens.Black, 10, 10, 10, 10);
    }
}

You don't need the Invalidate() call at all, since you're drawing to a buffer ( Bitmap ). 您根本不需要Invalidate()调用,因为您正在绘制到缓冲区( Bitmap )。 Just set the bitmap to pictureBox1.Image property: 只需将位图设置为pictureBox1.Image属性即可:

    private void OnTick(object sender, EventArgs e)
    {
        _graphics.Clear(Color.Aqua);
        _graphics.DrawRectangle(Pens.Black, 10, 10, 10, 10);
        pictureBox1.Image = _bitmap;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM