我正在做一个 8 谜题解算器,最终将每个节点(元素 0-8 的 int[])存储在路径中,以便将 block 按顺序放入堆栈中。我有一个显示 int[,]
的 WPF GUIforeach (var node in stack)
{
int[,] unstrung = node.unstringNode(node); // turns node of int[] into board of int[,]
blocks.setBoard(unstrung); // sets the board to pass in to the GUI
DrawBoard(); // Takes the board (int[,]) and sets the squares on the GUI to match it.
Thread.Sleep(500);
}
GUI 显示初始棋盘,然后在我单击解决后,最终(按顺序)棋盘正确显示。我想要做的是将板上的每个节点显示一段时间,最终到达按顺序的板。使用 Thread.Sleep,GUI 将在显示最终节点之前暂停设定的时间。关于为什么这段代码不会每 500 毫秒在每个节点显示一次棋盘,有什么想法吗?
以下是节点的 Console.Write 输出示例,供引用:
4,2,3,6,1,0,7,5,8
4,2,0,6,1,3,7,5,8
4,0,2,6,1,3,7,5,8
4,1,2,6,0,3,7,5,8
4,1,2,0,6,3,7,5,8
0,1,2,4,6,3,7,5,8
1,0,2,4,6,3,7,5,8
1,2,0,4,6,3,7,5,8
1,2,3,4,6,0,7,5,8
1,2,3,4,0,6,7,5,8
1,2,3,4,5,6,7,0,8
1,2,3,4,5,6,7,8,0
最佳答案
编辑:
由于我最初的答案因使用 Thread
而不是 Timer
而被否决,因此这里是一个使用计时器的示例。
使用线程的代码更短,我想快速给他一个解决方案。
此外,使用线程而不是计时器意味着他不需要以不同的方式传递参数或重构他的循环。
这就是为什么讨论替代解决方案的优缺点而不是简单地坚持只有一种正确的方法是个好主意。
使用timer_Tick
函数更新位置。
您可能会注意到,这使原始代码变得复杂,因为您必须以不同的方式传递参数并重新构造循环。
public partial class Form1 : Form
{
private Point pos = new Point(1,1);
private float[] vel = new float[2];
private Size bounds = new Size(20,20);
private Timer ticky = new Timer(); //System.Windows.Forms.Timer
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
ticky.Interval = 20;
ticky.Tick += ticky_Tick;
vel[0] = 4; vel[1] = 0;
ticky.Start();
}
void ticky_Tick(object sender, EventArgs e)
{
updatePosition();
//This tells our form to repaint itself (and call the OnPaint method)
this.Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.FillEllipse(new SolidBrush(Color.LightBlue), new Rectangle(pos, bounds));
}
private void updatePosition()
{
pos = new Point(pos.X + (int)vel[0], pos.Y + (int)vel[1]);
vel[1] += .5f; //Apply some gravity
if (pos.X + bounds.Width > this.ClientSize.Width)
{
vel[0] *= -1;
pos.X = this.ClientSize.Width - bounds.Width;
}
else if (pos.X < 0)
{
vel[0] *= -1;
pos.X = 0;
}
if (pos.Y + bounds.Height > this.ClientSize.Height)
{
vel[1] *= -.90f; //Lose some velocity when bouncing off the ground
pos.Y = this.ClientSize.Height - bounds.Height;
}
else if (pos.Y < 0)
{
vel[1] *= -1;
pos.Y = 0;
}
}
}
结果:
您可以使用计时器来执行各种延迟表单绘制:
原始解决方案:
//Create a separate thread so that the GUI thread doesn't sleep through updates:
using System.Threading;
new Thread(() => {
foreach (var node in stack)
{
//The invoke only needs to be used when updating GUI Elements
this.Invoke((MethodInvoker)delegate() {
//Everything inside of this Invoke runs on the GUI Thread
int[,] unstrung = node.unstringNode(node); // turns node of int[] into board of int[,]
blocks.setBoard(unstrung); // sets the board to pass in to the GUI
DrawBoard(); // Takes the board (int[,]) and sets the squares on the GUI to match it.
});
Thread.Sleep(500);
}
}).Start();
2022 年的解决方案:
等待 Task.Delay(500);
现在情况确实好多了。
关于c# - 每 2 秒更新一次 WPF GUI (C#),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23370601/