循环执行 UI 更新
我正在开发一个移动应用程序 UI,它有一个带有动量的面板(用于平滑滚动),并且我目前正在使用以下代码在平滑滚动期间更新 UI:
private void scrollKinetic()
{
while (_curState == States.KineticScroll)
{
// This gets how far the panel will move with the current velocity, then updates the velocity according to the current friction.
var distY = GetDistance(scrVelocity.Y);
var distX = GetDistance(scrVelocity.X);
if (distY + distX <= 0) // Friction will eventually make distX and distY both 0
{
_curState = States.Idle;
Invalidate();
break;
}
// CalculatePosition will move the panel accordingly.
CalculatePosition(distY, scrVelocity.Y, false);
CalculatePosition(distX, scrVelocity.X, true);
Invalidate();
friction++;
Application.DoEvents();
}
}
如您所见,Application.DoEvents(); 正在抬起它丑陋的头!我想摆脱它,但我想不出任何循环和更新 UI 的方法。任何帮助/想法都会很棒!
我在 .net CF 上这样做,但我认为这是一个设计问题,所以我认为平台不会太重要。
I am working on a mobile application UI that has a panel with momentum (for smooth scrolling) and I am currently updating the UI durring the smooth scrolling by using the following code:
private void scrollKinetic()
{
while (_curState == States.KineticScroll)
{
// This gets how far the panel will move with the current velocity, then updates the velocity according to the current friction.
var distY = GetDistance(scrVelocity.Y);
var distX = GetDistance(scrVelocity.X);
if (distY + distX <= 0) // Friction will eventually make distX and distY both 0
{
_curState = States.Idle;
Invalidate();
break;
}
// CalculatePosition will move the panel accordingly.
CalculatePosition(distY, scrVelocity.Y, false);
CalculatePosition(distX, scrVelocity.X, true);
Invalidate();
friction++;
Application.DoEvents();
}
}
As you can see, Application.DoEvents();
is rearing its ugly head! I want to get rid of it, but I can't think of any way to loop and update the UI. Any help/ideas would be excellent!
I'm doing this on the .net CF, but I think it's a design issue, so I don't think the platform will matter too much.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我将创建一个类似于“游戏循环”的计时器——每秒执行 x 次。
我还会跟踪自上次调用以来经过的时间,以便您可以根据经过的时间计算移动量。为了获得额外的性能,只有在有运动时才可以启动和停止计时器。
根据您使用的计时器类型,您可能需要将 UI 更新调用封送回 UI 线程。
I'd create a timer that would act like a "game loop" -- execute x times per second.
I would also keep track of how much time elapsed since the last call so that you can calculate how much to move based on that time elapsed. For extra performance, the timer could be started and stopped only if there is motion.
Depending on what kind of timer you use, you may need to marshal your UI update calls back to the UI thread.
您可以尝试删除循环(以及所有 App.DoEvent 调用),在 OnPaint() 方法中调用 KineticScroll,然后在 KineticScroll 方法中调用 Invalidate()。
我看到你有某种状态跟踪,所以你可以这样说:
在你的 OnPaint() 方法中,这样你只有在状态合适时才调用它。
基本上,您的循环从本地 while 循环转到:
OnPaint ->动感滚动 ->无效-> OnPaint...etc
这样你就可以得到相同的循环,无需调用 DoEvents!You could try and remove the loop (and all App.DoEvent calls), make a call to KineticScroll in your OnPaint() method, and then call Invalidate() in your KineticScroll method.
I see that you have some kind of state tracking, so you can say something like:
in your OnPaint() method, that way you only call it when your state is approprate.
Basically, your loop goes from a local while loop to:
OnPaint -> KineticScroll -> Invalidate -> OnPaint...etc
that way you get the same loop, w/o making a call to DoEvents!