3

我有四个PictureBoxes(每个 PictureBox 代表一个骰子)和一个每 100 毫秒更改一次源图片的计时器(作为 加载在内存中List<Bitmap> imagesLoadedFromIncludedResources)。

在此处输入图像描述

代码:

private List<PictureBox> dices = new List<PictureBox>();

private void timer_diceImageChanger_Tick(object sender, EventArgs e)
{
    foreach (PictureBox onePictureBox in dices)
    {
        oneDice.WaitOnLoad = false;
        onePictureBox.Image = //... ;
        oneDice.Refresh();
    }
}  

我需要一次更改所有图像- 此时,您可以看到图像正在从左到右更改,并且有一点延迟

我尝试了一个变体ThreadPictureBox使用这个答案Control.Invoke中的方法) - 它在视觉上稍微好一点,但并不完美。

4

3 回答 3

4

您可以尝试暂停表单的布局逻辑:

SuspendLayout();
// set images to pictureboxes
ResumeLayout(false);
于 2013-01-20T22:57:01.427 回答
0
Parallel.ForEach
(
    dices,
    new ParallelOptions { MaxDegreeOfParallelism = 4 },
    (dice) =>
    {
        dice.Image = ...;
        dice.WaitOnLoad = false;
        dice.Refresh();
    }
);

问题是 UI 控件只能从 UI 线程访问。如果要使用此方法,则必须创建 PictureBox 的副本,然后在操作完成后替换 UI 的。

另一种方法是创建两个 PictureBox,第一个位于另一个的顶部(隐藏后者)......您更改所有图像,然后,一旦处理完成,您就可以在后面迭代所有图像将它们放在顶部,这将减少延迟。

于 2013-01-20T22:49:57.017 回答
0

我会以不同的方式处理这个问题——我已经有一段时间没有玩过 WinForms 的东西了,但我可能会更好地控制图像的渲染。

在此示例中,我将图像全部放在一个垂直堆叠的源位图中,作为资源存储在程序集中:

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private Timer timer;

        private Bitmap dice;

        private int[] currentValues = new int[6];

        private Random random = new Random();

        public Form1()
        {
            InitializeComponent();
            this.timer = new Timer();
            this.timer.Interval = 500;
            this.timer.Tick += TimerOnTick;

            this.dice = Properties.Resources.Dice;
        }

        private void TimerOnTick(object sender, EventArgs eventArgs)
        {
            for (var i = 0; i < currentValues.Length; i++)
            {
                this.currentValues[i] = this.random.Next(1, 7);
            }

            this.panel1.Invalidate();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (this.timer.Enabled)
            {
                this.timer.Stop();
            }
            else
            {
                this.timer.Start();
            }
        }

        private void panel1_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.Clear(Color.White);

            if (this.timer.Enabled)
            {
                for (var i = 0; i < currentValues.Length; i++)
                {
                    e.Graphics.DrawImage(this.dice, new Rectangle(i * 70, 0, 60, 60), 0, (currentValues[i] - 1) * 60, 60, 60, GraphicsUnit.Pixel);
                }
            }
        }
    }
}

如果有帮助,来源在这里:http: //sdrv.ms/Wx2Ets

于 2013-01-20T23:03:37.850 回答