【问题标题】:Update multiple pictureboxes at the same time同时更新多个图片框
【发布时间】:2013-01-21 07:54:22
【问题描述】:

我有四个 PictureBoxes(每个 PictureBox 代表一个骰子)和一个 Timer,每 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();
    }
}  

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

我为每个PictureBox 尝试了一个Thread 的变体(使用this answer 中的Control.Invoke 方法) - 它在视觉上稍微好一点,但并不完美。

【问题讨论】:

  • 您是否预先缓存了要切换的Bitmap 对象?如果您每次都从磁盘加载,则会有轻微的延迟..
  • 是的,我将Form1_Load(...) Bitmapthis method 预缓存到List&lt;Bitmap&gt;
  • 您的源图像有多大?我无法想象像您在屏幕截图中显示的那样小的东西会出现明显的延迟(假设源图像实际上很小)。
  • 试试foreach (PictureBox onePictureBox in dices.AsParallel()
  • 实际上,图片稍大一些:“value 1” = 2,6KB,“value 6” = 9KB,所有图片的总大小约为 38KB。

标签: c# .net winforms picturebox


【解决方案1】:

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

SuspendLayout();
// set images to pictureboxes
ResumeLayout(false);

【讨论】:

    【解决方案2】:
    Parallel.ForEach
    (
        dices,
        new ParallelOptions { MaxDegreeOfParallelism = 4 },
        (dice) =>
        {
            dice.Image = ...;
            dice.WaitOnLoad = false;
            dice.Refresh();
        }
    );
    

    问题在于 UI 控件只能从 UI 线程访问。如果您想使用这种方法,您必须创建一个 PictureBox 的副本,然后在操作完成后替换 UI 的。

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

    【讨论】:

      【解决方案3】:

      我会以不同的方式处理这个问题——我已经有一段时间没有玩过 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

      【讨论】:

        猜你喜欢
        • 2020-04-12
        • 1970-01-01
        • 2014-07-30
        • 1970-01-01
        • 2019-02-16
        • 2014-10-14
        • 2019-11-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多