2008-12-26 38 views
0

我正在嘗試創建一個移動的矩形(rect)。這是相關的代碼:當鼠標在窗口中時WPF動畫變慢

let timer = new Threading.DispatcherTimer(); 
timer.Tick.Add(fun _ -> Canvas.SetLeft(rect, Canvas.GetLeft(rect)+0.01) |> ignore) 
timer.Start() 

問題是,如果我將鼠標移動到窗口上,動畫會變慢。如果我設置定時器的時間間隔:

timer.Interval <- TimeSpan.FromMilliSeconds(30.0) 

然後動畫根本不起作用。我究竟做錯了什麼?謝謝。

回答

4

我有兩個建議:

1)如果您使用F#交互檢查已安裝了世界糧食計劃署的事件循環。 F#交互默認情況下設置了winforms eventloop,在winforms和WFP事件循環之間有一些兼容性,但並非所有工作都能正確執行。要安裝事件循環使用下面的腳本:

#light 

// When running inside fsi, this will install a WPF event loop 
#if INTERACTIVE 

#I "c:/Program Files/Reference Assemblies/Microsoft/Framework/v3.0";; 
#I "C:/WINDOWS/Microsoft.NET/Framework/v3.0/WPF/";; 
#r "presentationcore.dll";; 
#r "presentationframework.dll";; 
#r "WindowsBase.dll";; 

module WPFEventLoop = 
    open System 
    open System.Windows 
    open System.Windows.Threading 
    open Microsoft.FSharp.Compiler.Interactive 
    open Microsoft.FSharp.Compiler.Interactive.Settings 
    type RunDelegate<'b> = delegate of unit -> 'b 

    let Create() = 
     let app = 
      try 
       // Ensure the current application exists. This may fail, if it already does. 
       let app = new Application() in 
       // Create a dummy window to act as the main window for the application. 
       // Because we're in FSI we never want to clean this up. 
       new Window() |> ignore; 
       app 
      with :? InvalidOperationException -> Application.Current 
     let disp = app.Dispatcher 
     let restart = ref false 
     { new IEventLoop with 
      member x.Run() = 
       app.Run() |> ignore 
       !restart 
      member x.Invoke(f) = 
       try disp.Invoke(DispatcherPriority.Send,new RunDelegate<_>(fun() -> box(f()))) |> unbox 
       with e -> eprintf "\n\n ERROR: %O\n" e; rethrow() 
      member x.ScheduleRestart() = () 
       //restart := true; 
       //app.Shutdown() 
     } 
    let Install() = fsi.EventLoop <- Create() 

WPFEventLoop.Install();; 

#endif 

2)我沒有測試過這太清楚,但我想用一個動畫故事板會給濃煙更一致的結果,而不是使用一個計時器。我認爲這將看起來像(改變寬度屬性還沒有計算出如何改變位置):

#light 

open System 
open System.Windows 
open System.Windows.Controls 
open System.Windows.Shapes 
open System.Windows.Media 
open System.Windows.Media.Animation 


let rect = new Rectangle(Fill = new SolidColorBrush(Colors.Red), Height = 20., Width = 20., Name = "myRectangle") 

let canvas = 
    let c = new Canvas() 
    c.Children.Add(rect) |> ignore 
    c 

NameScope.SetNameScope(canvas, new NameScope()); 
canvas.RegisterName(rect.Name, rect) 

let window = new Window(Content = canvas) 

let nfloat f = new Nullable<float>(f) 

let myDoubleAnimation = new DoubleAnimation(From = nfloat 20.0, To = nfloat 50.0, 
              Duration = new Duration(TimeSpan.FromSeconds(5.)), 
              RepeatBehavior = RepeatBehavior.Forever) 
let myStoryboard = 
    let sb = new Storyboard() 
    sb.Children.Add(myDoubleAnimation) 
    sb 

Storyboard.SetTargetName(myDoubleAnimation, rect.Name); 
Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Rectangle.WidthProperty)) 

rect.Loaded.Add(fun _ -> myStoryboard.Begin canvas) 

let main() = 
    let app = new Application() 
    app.Run window |> ignore 

[<STAThread>] 
do main() 
+0

感謝您的建議。因爲你說這可能是F#交互式的問題,我在C#中做了同樣的例子。 C#代碼也沒有工作。我的問題是每個tick的0.01移動太低。我認爲1.0將是整個窗口,所以0.01將是窗口的1%。 – Jules 2008-12-26 10:53:58

相關問題