pictureBox一步一步运行的很好,但是执行的时候好像每次都执行两次timer tick
pictureBox works fine step by step, but when executed, it seems to execute the timer tick twice each time
我正在制作一个简单的屏幕保护程序,它显示一组图片,在显示所有图片之前不重复它们。问题是,图片框正在跳过一些更新或其他内容,或者在两张图片之间快速切换。其他时候它在同一张图片上停留的时间太长。
它在调试模式下工作得很好,即使我多次点击继续,除非我点击继续太快。
图片框更新与每 2 秒触发一次的计时器相关联。
private void timer1_Tick(object sender, EventArgs e)
{
if (pictureBox1.Image != null) { pictureBox1.Image.Dispose();}
pictureBox1.Image = (Image)siguienteImagenAMostrar.Clone();
//siguienteImagenAMostrar is an Image, and it´s the one i want to show next
pictureBox1.Invalidate();
pictureBox1.Update();
if (siguienteImagenAMostrar != null) { siguienteImagenAMostrar.Dispose(); }
siguienteImagenAMostrar = siguienteImagen(); //I try to preload the Image
}
这是 siguienteImagen() 代码,以防它与我使用的 Random
有关:
private Image siguienteImagen()
{
int imagenAmostrar;
do
{
imagenAmostrar = rand.Next(0, files.Length);
} while (currentImage == imagenAmostrar && files.Length > 1);
int original = imagenAmostrar;
if (mostrada[imagenAmostrar]) {
imagenAmostrar = (imagenAmostrar + 1) % files.Length;
while (mostrada[imagenAmostrar] && original != imagenAmostrar)
{
imagenAmostrar = (imagenAmostrar + 1) % files.Length;
}
if (imagenAmostrar == original)
{
mostrada = Enumerable.Repeat(false, files.Length).ToArray();
}
}
mostrada[imagenAmostrar] = true;
currentImage = imagenAmostrar;
string imagenMostrarString = files[imagenAmostrar];
return Image.FromFile(imagenMostrarString);
}
编辑:这个功能似乎不是问题,因为简单地选择下一张图片 currentImage = (currentImage + 1) % files.Length
仍然存在无法正确显示图片的问题。
另外 mostrada
是一个布尔数组,它知道该图片是否已经显示。 files
是一个包含图片路径的数组。相同的索引代表两者上的相同图像。
我敢打赌,如果您避免获得可能已被使用的随机数,这将使您的代码更清晰,对您和执行的工作更少。使用布尔数组来跟踪这一点可能会浪费循环时间,因为随机数生成器可能会生成一个已经选择的值。我想你会想避免这种情况。
一种可能的解决方案是从图像集合中创建 List<int>
索引。例如图像集合有五 (5) 张图像,那么这个列表看起来像......
Index value
0 0
1 1
2 2
3 3
4 4
我们希望“保留”此列表的副本,因为在浏览完所有图像后我们将需要它。因此,假设 rand.Next(0, listAbove.Count);
中的第一个随机数是 3。然后我们将从索引 3 中获取值,这也是索引三 (3)。我们在索引三 (3) 处获取图像并从列表中“删除”三 (3)。在此之后,列表看起来像......
Index value
0 0
1 1
2 2
3 4
以这种方式继续,直到列表为空,此时我们只需重新填充即可。
鉴于这会创建两个 List<int>
变量…
List<int> fullImageListIndexes;
List<int> currentImageIndexes;
Random rand = new Random();
现在我们需要一种方法,该方法 returns 从该列表中随机获取图像。 Random 调用的边界将为列表大小的零 (0)。找到随机索引后,我们将其从列表中“删除”。这将减小列表大小并保证始终只有一 (1) 次调用随机数生成器。以这种方式继续,我们只需要检查图像列表是否为空,这表明我们已经使用了所有图像并且需要用原始值“重新填充”列表。我希望这是有道理的。
下面是returns下一个随机图像的方法...首先检查列表是否为空,如果是,只需重新填充即可。根据列表的大小获取下一个随机索引,获取原始图像索引的值,然后获取该图像,最后“删除”我们刚刚使用的图像索引。
private Image GetNextRandomImage() {
if (currentImageIndexes.Count == 0) {
//textBox1.Text += "Refill" + Environment.NewLine;
currentImageIndexes = new List<int>(fullImageListIndexes);
}
int randomIndex = rand.Next(0, currentImageIndexes.Count);
int valueToRemove = currentImageIndexes[randomIndex];
Image nextImage = imageList1.Images[valueToRemove];
currentImageIndexes.Remove(valueToRemove);
//textBox1.Text += "Tick : RI: " + randomIndex + " SV: " + valueToRemove + Environment.NewLine;
return nextImage;
}
定时器滴答事件…
private void timer1_Tick(object sender, EventArgs e) {
pictureBox1.Image = GetNextRandomImage();
}
最后把它们放在一起...... imageList1
是一个 .Net 图像列表对象,其图像集合中添加了一些图像…
public Form1() {
InitializeComponent();
fullImageListIndexes = new List<int>();
for (int i = 0; i < imageList1.Images.Count; i++) {
fullImageListIndexes.Add(i);
}
currentImageIndexes = new List<int>(fullImageListIndexes);
}
希望这是有道理的。
发生的事情是我在 form_load()
函数中有 timer1.Tick += new EventHandler(timer1_Tick);
。我仍然不确定为什么它在逐步模式下工作
删除明显多余的 EventHandler,解决了我的问题。
我正在制作一个简单的屏幕保护程序,它显示一组图片,在显示所有图片之前不重复它们。问题是,图片框正在跳过一些更新或其他内容,或者在两张图片之间快速切换。其他时候它在同一张图片上停留的时间太长。
它在调试模式下工作得很好,即使我多次点击继续,除非我点击继续太快。
图片框更新与每 2 秒触发一次的计时器相关联。
private void timer1_Tick(object sender, EventArgs e)
{
if (pictureBox1.Image != null) { pictureBox1.Image.Dispose();}
pictureBox1.Image = (Image)siguienteImagenAMostrar.Clone();
//siguienteImagenAMostrar is an Image, and it´s the one i want to show next
pictureBox1.Invalidate();
pictureBox1.Update();
if (siguienteImagenAMostrar != null) { siguienteImagenAMostrar.Dispose(); }
siguienteImagenAMostrar = siguienteImagen(); //I try to preload the Image
}
这是 siguienteImagen() 代码,以防它与我使用的 Random
有关:
private Image siguienteImagen()
{
int imagenAmostrar;
do
{
imagenAmostrar = rand.Next(0, files.Length);
} while (currentImage == imagenAmostrar && files.Length > 1);
int original = imagenAmostrar;
if (mostrada[imagenAmostrar]) {
imagenAmostrar = (imagenAmostrar + 1) % files.Length;
while (mostrada[imagenAmostrar] && original != imagenAmostrar)
{
imagenAmostrar = (imagenAmostrar + 1) % files.Length;
}
if (imagenAmostrar == original)
{
mostrada = Enumerable.Repeat(false, files.Length).ToArray();
}
}
mostrada[imagenAmostrar] = true;
currentImage = imagenAmostrar;
string imagenMostrarString = files[imagenAmostrar];
return Image.FromFile(imagenMostrarString);
}
编辑:这个功能似乎不是问题,因为简单地选择下一张图片 currentImage = (currentImage + 1) % files.Length
仍然存在无法正确显示图片的问题。
另外 mostrada
是一个布尔数组,它知道该图片是否已经显示。 files
是一个包含图片路径的数组。相同的索引代表两者上的相同图像。
我敢打赌,如果您避免获得可能已被使用的随机数,这将使您的代码更清晰,对您和执行的工作更少。使用布尔数组来跟踪这一点可能会浪费循环时间,因为随机数生成器可能会生成一个已经选择的值。我想你会想避免这种情况。
一种可能的解决方案是从图像集合中创建 List<int>
索引。例如图像集合有五 (5) 张图像,那么这个列表看起来像......
Index value
0 0
1 1
2 2
3 3
4 4
我们希望“保留”此列表的副本,因为在浏览完所有图像后我们将需要它。因此,假设 rand.Next(0, listAbove.Count);
中的第一个随机数是 3。然后我们将从索引 3 中获取值,这也是索引三 (3)。我们在索引三 (3) 处获取图像并从列表中“删除”三 (3)。在此之后,列表看起来像......
Index value
0 0
1 1
2 2
3 4
以这种方式继续,直到列表为空,此时我们只需重新填充即可。
鉴于这会创建两个 List<int>
变量…
List<int> fullImageListIndexes;
List<int> currentImageIndexes;
Random rand = new Random();
现在我们需要一种方法,该方法 returns 从该列表中随机获取图像。 Random 调用的边界将为列表大小的零 (0)。找到随机索引后,我们将其从列表中“删除”。这将减小列表大小并保证始终只有一 (1) 次调用随机数生成器。以这种方式继续,我们只需要检查图像列表是否为空,这表明我们已经使用了所有图像并且需要用原始值“重新填充”列表。我希望这是有道理的。
下面是returns下一个随机图像的方法...首先检查列表是否为空,如果是,只需重新填充即可。根据列表的大小获取下一个随机索引,获取原始图像索引的值,然后获取该图像,最后“删除”我们刚刚使用的图像索引。
private Image GetNextRandomImage() {
if (currentImageIndexes.Count == 0) {
//textBox1.Text += "Refill" + Environment.NewLine;
currentImageIndexes = new List<int>(fullImageListIndexes);
}
int randomIndex = rand.Next(0, currentImageIndexes.Count);
int valueToRemove = currentImageIndexes[randomIndex];
Image nextImage = imageList1.Images[valueToRemove];
currentImageIndexes.Remove(valueToRemove);
//textBox1.Text += "Tick : RI: " + randomIndex + " SV: " + valueToRemove + Environment.NewLine;
return nextImage;
}
定时器滴答事件…
private void timer1_Tick(object sender, EventArgs e) {
pictureBox1.Image = GetNextRandomImage();
}
最后把它们放在一起...... imageList1
是一个 .Net 图像列表对象,其图像集合中添加了一些图像…
public Form1() {
InitializeComponent();
fullImageListIndexes = new List<int>();
for (int i = 0; i < imageList1.Images.Count; i++) {
fullImageListIndexes.Add(i);
}
currentImageIndexes = new List<int>(fullImageListIndexes);
}
希望这是有道理的。
发生的事情是我在 form_load()
函数中有 timer1.Tick += new EventHandler(timer1_Tick);
。我仍然不确定为什么它在逐步模式下工作
删除明显多余的 EventHandler,解决了我的问题。