C# 同时更新多个pictureboxes
我有四个C# 同时更新多个pictureboxes,c#,.net,winforms,picturebox,C#,.net,Winforms,Picturebox,我有四个图片盒(每个图片盒代表一个骰子)和一个每100毫秒更改一次的源图片(作为列表图片加载到内存中,从包含的资源中加载) 代码: 私有列表骰子=新列表(); 私有无效计时器\u diceImageChanger\u勾号(对象发送方,事件参数e) { foreach(PictureBox一个PictureBox在骰子中) { oneDice.WaitOnLoad=false; onePictureBox.Image=/; oneDice.Refresh(); } } 我需要一次更改所有图
图片盒
(每个图片盒代表一个骰子)和一个每100毫秒更改一次的源图片(作为列表图片加载到内存中,从包含的资源中加载)
代码:
私有列表骰子=新列表();
私有无效计时器\u diceImageChanger\u勾号(对象发送方,事件参数e)
{
foreach(PictureBox一个PictureBox在骰子中)
{
oneDice.WaitOnLoad=false;
onePictureBox.Image=/;
oneDice.Refresh();
}
}
我需要一次更改所有图像-此时,您可以看到图像是以较小的延迟从左向右更改的
我为每个PictureBox
(使用来自的方法)尝试了一个线程的变体,它在视觉上稍好一些,但并不完美
Parallel.ForEach
(
dices,
new ParallelOptions { MaxDegreeOfParallelism = 4 },
(dice) =>
{
dice.Image = ...;
dice.WaitOnLoad = false;
dice.Refresh();
}
);
问题是UI控件只能从UI线程访问。如果要使用这种方法,必须创建PictureBox的副本,然后在操作完成后替换UI
另一种方法是创建两个PictureBox,第一个正好位于另一个的顶部(隐藏后者)。。。您可以更改所有图像,然后在处理完成后,迭代背面的所有图像,将它们放在顶部,这样会减少延迟。您可以尝试暂停表单的布局逻辑:
SuspendLayout();
// set images to pictureboxes
ResumeLayout(false);
我会用不同的方法来处理这个问题——我已经有一段时间没有玩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);
}
}
}
}
}
命名空间窗口窗体应用程序1
{
公共部分类Form1:Form
{
私人定时器;
私人位图骰子;
私有int[]当前值=新int[6];
私有随机=新随机();
公共表格1()
{
初始化组件();
this.timer=新计时器();
此.timer.Interval=500;
this.timer.Tick+=TimerOnTick;
this.dice=Properties.Resources.dice;
}
私有void TimerOnTick(对象发送方,EventArgs EventArgs)
{
对于(var i=0;i
如果有帮助,源代码就在这里:您是否预缓存了要关闭的位图
对象?如果每次从磁盘加载,都会有一点延迟。是的,我将格式中的预缓存加载(…)
位图
放入列表中,源图像有多大?我无法想象屏幕截图中显示的这么小的东西会有明显的延迟(假设源图像真的那么小)。请尝试使用foreach(PictureBox-onePictureBox-in-dices.AsParallel()
事实上,图像稍大一些:“值1”=2,6KB,“值6”=9KB,所有图像的总大小约为38KB。
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);
}
}
}
}
}