【问题标题】:C# winforms problems drawing to picturebox using collection?C# winforms 使用集合绘制到图片框的问题?
【发布时间】:2012-10-29 17:00:11
【问题描述】:

表单包含一个图片框(picturebox1)和一个定时器控件(timer1)...

基本上在启动时,我会创建一个包含 5 个像素类实例的列表集合。当计时器触发时,我调用调用绘制事件的图片框的刷新。在绘制事件中,我遍历列表集合并调用每个像素的绘制方法。

我遇到的问题是只显示一个像素...也就是说.. 除非我在添加像素的位置设置中断,否则继续,然后再次中断并重复,直到创建所有 pthe 像素.然后由于某种原因所有的像素都出现了......

谁能告诉我为什么我只能看到一个像素?

public partial class Form1 : Form
{
    List<Pixel> pixels = new List<Pixel>();

    public Form1()
    {            
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        for (int ii = 0; ii < 5; ii++)
            pixels.Add(new Pixel(pictureBox1));  // <- breakpoint here...?
    }

    private void pictureBox1_Paint(object sender, PaintEventArgs e)
    {
        foreach (Pixel p in pixels)
            p.Draw(e, pictureBox1);
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        pictureBox1.Refresh();
    }
}

public class Pixel
{
    Random r = new Random(DateTime.Now.Millisecond);

    public Point Position { get; set; }

    public Pixel(PictureBox src) 
    {
        Position = new Point(r.Next(0, src.Width), r.Next(0, src.Height));
    }

    public void Draw(PaintEventArgs e, PictureBox src)
    {
        e.Graphics.DrawRectangle(new Pen(Color.Black), Position.X, Position.Y, 1, 1);
    }
}

我的原始代码做了更多......但我把它全部去掉并得到了相同的结果。

【问题讨论】:

    标签: c# winforms


    【解决方案1】:

    由于每次调用 Random r = new Random(DateTime.Now.Millisecond) 时都使用相同的种子值,因此像素会出现在完全相同的位置。我将 Random 声明移至主类并将其传递给像素类。现在它可以正常工作了。

    public partial class Form1 : Form
    {
        Random r = new Random(DateTime.Now.Millisecond);
        List<Pixel> pixels = new List<Pixel>();
    
        public Form1()
        {            
            InitializeComponent();
        }
    
        private void Form1_Load(object sender, EventArgs e)
        {
            for (int ii = 0; ii < 5; ii++)
            {
                pixels.Add(new Pixel(pictureBox1, r));
            }
        }
    
        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            foreach (Pixel p in pixels)
                p.Draw(e, pictureBox1);
        }
    
        private void timer1_Tick(object sender, EventArgs e)
        {
            pictureBox1.Refresh();
        }
    }
    
    public class Pixel
    {
        public Point Position { get; set; }
    
        public Pixel(PictureBox src, Random r) 
        {
            Position = new Point(r.Next(0, src.Width), r.Next(0, src.Height));
        }
    
        public void Draw(PaintEventArgs e, PictureBox src)
        {
            e.Graphics.DrawRectangle(new Pen(Color.Black), Position.X, Position.Y, 1, 1);
        }
    }
    

    【讨论】:

    • 只是一个建议,使用 Invalidate() 而不是 Refresh()。
    【解决方案2】:

    这是因为您的像素类的所有 5 个实例上的随机化器都使用完全相同的种子(这一切都发生在相同的毫秒值上)。不要宽恕使用 Thread.Sleep,至少暴露问题的最快“修复”是将您的 form_load 事件更改为如下所示(您也可以重构随机化的方式):

        private void Form1_Load(object sender, EventArgs e)
        {
            for (int ii = 0; ii < 5; ii++)
            {
                Thread.Sleep(1);
                pixels.Add(new Pixel(pictureBox1));
            }
        }
    

    【讨论】:

    • 你应该重构Random,这样你就可以重用它,而不是睡一会儿。请注意,虽然它不再产生相同的结果,但不会产生几乎均匀分布的结果; Random 会有偏差,因为每个种子只能获得一个随机数,因此该数字仅与该种子一样随机(这不是随机的,它将是顺序值)。
    • 我没有提供一个理想的方法,而是一种暴露导致他问题的问题的方法。这一点我是很清楚的。我可以理解您的建议会产生更均匀分布的结果,但这不是当前的问题或问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多