我创建了一个表格,其中有一个'矩形'项目的位置需要动态更改,以便不断移动'效果得到了。
我希望黑色矩形在表单的边界内继续移动。我试过这个:
//globally decalred variables
Random locationRandomizer = new Random();
int count = 0;
private void Form1_Load(object sender, EventArgs e)
{
Thread movementThread = new Thread(new ThreadStart(movementFunction));
movementThread.Start();
}
public void movementFunction()
{
try
{
int x;
int y;
int windowHeight = this.Height;
int windowWidth = this.Width;
do
{
x = locationRandomizer.Next(1, windowWidth);
y = locationRandomizer.Next(1, windowWidth);
animalDot.Location = new Point(x, y);
}
while (count == 0);
}
catch (Exception ex)
{
}
}
但是在加载表单时矩形会移动ONCE,之后不会更改。我做错了什么?
当我删除空的try catch块时,这就是我得到的错误:
跨线程操作无效:控制' shapeContainer1'从创建它的线程以外的线程访问。
答案 0 :(得分:1)
您收到该错误是因为您正在从非UI线程访问UI元素。您可以通过调用控件上的Invoke方法绕过它,将调用封送回UI线程:
textBox1.Invoke((MethodInvoker)(() => textBox1.Location = new Point(x, y)));
执行一些定期影响用户界面的代码的更好方法是使用System.Windows.Forms.Timer
,这是Timer
控件,您可以放入设计器中。
订阅Tick
事件,该事件在UI线程上运行并避免上述错误。
private void timer_Tick(object sender, EventArgs e)
{
var x = locationRandomizer.Next(1, Width - animalDot.Width);
var y = locationRandomizer.Next(1, Height - animalDot.Height);
animalDot.Location = new Point(x, y);
}
然后在构造函数中,您可以将间隔设置为相对较小的值并启用计时器。
timer.Interval = 100;
timer.Enabled = true;
答案 1 :(得分:0)
你可以制作一个自主的“可移动的”'从Rectange下降并包含在内部计时器实例中的类。当计时器触发时,添加一个'速度'增加到该位置。对于碰撞,你可以下降到一个可碰撞的'当它移动时,迭代所有其他Collidables的集合并触发一个OnCollision'将碰撞对象作为参数的事件,以便您可以决定如何处理与墙壁,其他可移动物体等的碰撞。