2011-03-24 62 views
1

我上有气势面板(用于平滑滚动)的移动应用程序用户界面的工作进行UI更新和我目前正在更新UI durring通过使用下面的代码平滑滚动:在一个循环中

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();正在饲养它的丑陋的头!我想摆脱它,但我想不出任何方式来循环和更新用户界面。任何帮助/想法都会很棒!

我在.net CF上这样做,但我认为这是一个设计问题,所以我认为平台不会太重要。

+0

无法从scrVelocity生成任何事件?然后使用计时器。 – 2011-03-24 04:13:15

回答

1

您可以尝试并删除循环(以及所有App.DoEvent调用),在您的OnPaint()方法中调用KineticScroll,然后在您的KineticScroll方法中调用Invalidate()。

我看到你有某种状态跟踪的,所以你可以这样说:

if(_curState == States.KineticScroll) 
    KineticScroll(); 
在您的OnPaint()方法

,这样,你只把它当你的状态是approprate。

基本上,你的循环从本地while循环转到:OnPaint -> KineticScroll -> Invalidate -> OnPaint...etc这样你就可以得到相同的循环,而不需要拨打DoEvents!

1

我会创建一个像“游戏循环”一样的计时器 - 每秒执行x次。
我还会记录自上次调用以来经过了多少时间,以便您可以根据该时间过去计算需要移动多少时间。为了获得额外的性能,定时器只有在运动时才能启动和停止。

根据您使用的定时器类型,您可能需要将您的UI更新调用封送回UI线程。

+0

我最初做了一个带有Timer的版本,但它感觉像是在拼图...我最初设置的时间间隔为30 fps,但它非常不稳定,然后我将刷新时间间隔设置为10 fps,而且稍微好一些,但是仍然不如DoEvent循环那样流畅。什么是使定时器更流畅的好方法? – 2011-03-24 04:36:49

+0

您是否跟踪自定时器上次触发以来已经过了多长时间并移动距离= vel *时间?定时器不会在预定的时间发出回调。 – foson 2011-03-24 13:53:33