我有这个foreach循环来迭代窗体中的控件,这样我就可以找到我用箭头键移动的picturebox,并检查它是否通过标记与其他picturebox冲突。现在我想检查picturebox是否与带有标记“portal”的picturebox冲突,如果是,它必须打开一个新窗体并关闭/隐藏当前窗体,我做到了,而且运行良好,唯一的问题是它打开第二个表单13次,我想这是因为它运行了13次foreach循环,运行了13次那3行代码,但我希望它们只运行一次,打开新表单,关闭/隐藏当前表单一次。
private void moveTimerEvent(object sender, EventArgs e)
{
if (moveLeft == true && pictureBox1.Left > 10)
{
pictureBox1.Left -= speed;
}
if (moveRight == true && pictureBox1.Left < 1850) //right border of the screen.
{
pictureBox1.Left += speed;
}
if (moveUp == true && pictureBox1.Top > 10)
{
pictureBox1.Top -= speed;
}
if (moveDown == true && pictureBox1.Top < 962) //bottom border of the screen.
{
pictureBox1.Top += speed;
}
foreach (Control x in this.Controls) //foreach loop that I am referring to
{
if (x is PictureBox && (string)x.Tag == "wall")
{
if (pictureBox1.Bounds.IntersectsWith(x.Bounds))
{
pictureBox1.Location = new Point(123, 962);
}
}
else
{
if (x is PictureBox && (string)x.Tag == "portal") //if statement that I am also referring to
{
if (pictureBox1.Bounds.IntersectsWith(x.Bounds)) //if statement that runs 13 times, but only has to run once
{
Form2 f2 = new Form2(); //open form2
f2.Show(); //show it
this.Hide(); //close this one
}
}
}
}
}
我试着在我只想运行一次的代码后面添加一个break,但它仍然打开了新窗体13次。我希望break只运行一次,然后停止运行那些行。
1条答案
按热度按时间qeeaahzv1#
你的帖子描述了你在代码中显示的定时器方案和内部循环中遇到的一些问题。但是你的实际目标是什么呢?你在帖子中说它的 * 存在理由 * 是:
[...]这样我就可以找到我用箭头键移动的图片框,并通过标签检查它是否与其他图片框冲突。
这"可能"被认为是X-Y Problem,因为可能有比定时器更优的方式来实现您最初想要做的事情(因为间隔为20ms的定时器可能会出现一些竞争条件,使其难以按预期启动和停止)。
考虑自定义
PictureBox
,当按下Left、Right、Up或Down时,它可以MoveProgrammatically(Keys direction)
。它还需要根据IsCurrentMoveTarget
属性跟踪这个"特定"图片框是否是应该移动的那个。当它"确实"成为当前移动目标时,它会通知所有"其他"示例它们不再是。Move方法具有碰撞检测功能,并在即将发生时激发一个可取消事件。
确定这是否是要移动的控件,以及是否绘制聚焦框。
主窗体使用MessageFilter表示Up Down Left Right键事件,并将任何事件广播到它可能包含的所有
ArrowKeyPictureBox
示例。显示碰撞状态: