1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies. Weitere Informationen

[C#] Laufschrift läuft unsanft / unschön

Dieses Thema im Forum ".NET WPF & Silverlight" wurde erstellt von Lesterdor, 14. März 2014.

  1. Lesterdor

    Lesterdor Erfahrenes Mitglied

    Guten Abend liebe Community,

    ich habe mir einen kleinen Prototypen für eine Laufschrift erstellt. Dabei "läuft" das Label vom rechten Bildschirmrand zum Linken. Dort angekommen, fängt es wieder bei rechts an, sodass es unendlich wirkt. Vergleichbar mit einem Newsticker.

    Mein Problem ist leider, dass das Label sehr ruckelartig seine Position verschiebt. Es wirkt einfach unsanft/unsauber. Ich verschiebe das Label alle 33 ms um 1.0 nach links.

    Mein Renderer läuft hardwareseitig ( Tier 2).
    Framework: 4.5
    XAML:
    Code (Text):
    1. <Window x:Class="Canny.MainWindow"
    2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4.         Title="MainWindow" Height="350" Width="811" Name="main">
    5.     <Canvas Name="myCanvas" Background="Black">
    6.         <Label Name="lb1" Content="Lauftext+++" Foreground="WhiteSmoke" FontSize="25" Canvas.Left="618" Canvas.Top="10" FontFamily="Courier New" FontWeight="ExtraBold" FontStretch="UltraExpanded"/>
    7.     </Canvas>
    8. </Window>
    XAML.CS:
    Code (Text):
    1. using System;
    2. using System.Windows;
    3. using System.Windows.Controls;
    4. using System.Windows.Media;
    5. using System.Windows.Threading;
    6.  
    7. namespace Canny
    8. {
    9.     /// <summary>
    10.     /// Interaktionslogik für MainWindow.xaml
    11.     /// </summary>
    12.     public partial class MainWindow : Window
    13.     {
    14.         DispatcherTimer timer;
    15.         double newPos;
    16.         readonly double actualWidthLb;
    17.         int renderingTier;
    18.         public MainWindow()
    19.         {
    20.             InitializeComponent();
    21.             timer = new DispatcherTimer();
    22.             timer.Interval = TimeSpan.FromMilliseconds(33.0);
    23.             timer.Tick += timer_Tick;
    24.             newPos = myCanvas.ActualWidth;
    25.             actualWidthLb = lb1.ActualWidth;
    26.             timer.Start();
    27.             renderingTier = (RenderCapability.Tier >> 16);
    28.            
    29.         }
    30.  
    31.         void timer_Tick(object sender, EventArgs e)
    32.         {
    33.             newPos -= 1.0;
    34.             Canvas.SetLeft(lb1,newPos);
    35.             if (Canvas.GetLeft(lb1) + actualWidthLb <= 0)
    36.             {
    37.                 Canvas.SetLeft(lb1, myCanvas.ActualWidth);
    38.                 newPos = myCanvas.ActualWidth;
    39.             }
    40.         }
    41.     }
    42. }
    Über Ratschläge bedanke ich mich im Voraus und verbleibe

    mit freundlichen Grüßen

    - Les
     
  2. ademo

    ademo Mitglied

    Huhu

    Habe es gerade mal ausprobiert scheint aber nur ganz leicht zu ruckeln. Ich denke mal das 1.0 ein zu grosser wert ist, ich hab das Gefühl mit 15ms und 0.5newPos geht es ganz flüssig.
     
  3. ksk

    ksk Erfahrenes Mitglied

    Hallo Les,

    der SilverLight Profi bin ich nicht aber ich hatte mal ein Projekt in welcher ich eine Animation realisieren musste.
    Habe dazu einen DispatcherTimer genommen und jede Millisekunde eine Methode aufgerufen in der die Poition
    geändert wurde. Das sah sehr flüssig und gschmeidig aus.
    Jedoch änderte ich dabei den Margin Wert des jeweiligen Objektes.
    Code (Text):
    1. private void StartAnim()
    2. {
    3.   dpt = new System.Windows.Threading.DispatcherTimer();
    4.   dpt.Interval = new TimeSpan(0, 0, 0, 0, 1);
    5.   dpt.Tick += new EventHandler(dpt_Tick);
    6.   dpt.Start();
    7. }
    8. void dpt_Tick(object sender, EventArgs e)
    9. {
    10.   if (img.Margin.Left < 28)
    11.   {
    12.   img.Margin = new Thickness(Convert.ToDouble(img.Margin.Left + 2),
    13.   img.Margin.Top, img.Margin.Right, img.Margin.Bottom);
    14.   }
    15.   else
    16.   { img.Margin = new Thickness(28, img.Margin.Top, img.Margin.Right, img.Margin.Bottom); }
    17. }
    Ist zwar keine Elegante Lösung aber probier mal obst ein Unterschied merkst.
    Übrigens, über Expression Blend kannst diese Sachen ähnlich wie in Flash über
    eine eigene TimeLine usw. realisieren genannt Storyboards.
    Dies auch über Code-Behind natürlich, bsp über ein PlaneProjection
    Code (Text):
    1. PlaneProjection pp = new PlaneProjection();
    2. pp.LocalOffsetX = x;
    3. pp.LocalOffsetY = y;
    4. pp.LocalOffsetZ = z;
    5. obj.Projection = pp; // die Projection an das Objekt zuweisen
    Hier ein Ansatz in XAML
    Code (Text):
    1. <Canvas
    2. xmlns="http://schemas.microsoft.com/client/2007"
    3.   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    4. <Canvas.Triggers>
    5. <EventTrigger RoutedEvent="Canvas.Loaded">
    6.   <EventTrigger.Actions>
    7.   <BeginStoryboard>
    8.   <Storyboard>
    9.   <DoubleAnimation Storyboard.TargetName="objectToAnimate"
    10.   Storyboard.TargetProperty="(Canvas.Top)"
    11.   To="350" Duration="0:0:3"/>
    12.   </Storyboard>
    13.   </BeginStoryboard>
    14.   </EventTrigger.Actions>
    15. </EventTrigger>
    16. </Canvas.Triggers>
    17. <Rectangle x:Name="objectToAnimate" Canvas.Left="5" Fill="Red"
    18.   Canvas.Top="5" Height="25" Width="25" Stroke="Blue" StrokeThickness="3" />
    19. </Canvas>
    Schau dir noch dazu folgende Links an
    http://msdn.microsoft.com/en-us/library/cc189019(VS.95).aspx
    http://msdn.microsoft.com/en-us/library/ms742305%28v=vs.110%29.aspx
    http://msdn.microsoft.com/en-us/library/cc189090%28v=vs.95%29.aspx


    Lg
    ksk
     
  4. Namae

    Namae Grünschnabel

    Hallo,

    es ruckelt, weil du einen Timer verwendest.

    Timer werden nicht immer genau dann ausgelöst wann man es erwartet - deshalb ruckelts bei dir. Man könnte es mehr als Wunschzeit betrachten(hängt davon ab wie stark dein programm/system ausgelastet ist), zumal man einen Timer minimal nur alle 15 komma irgendwas Millisekunden einstellen kann. Man kann zwar 1 ms einstellen, wird jedoch nie an diesen Wert kommen, Grund dafür ist der Taktquartz deines Rechners.

    Timer zu verwenden ist ziemlich...uncool. Ist zwar sehr leicht, aber für etwas gehobene Anforderungen absolut unpassend.

    Wenn du deine Berechnung in einen Thread auslagerst und die Position über einen Timespan berechnest, dürfte es dein Problem lösen. Am einfachsten ist du verwendest den ThreadPool und mittels Dispatcher.Invoke() kannst du deine Aufrufe in den UI-Thread synchronisieren.

    vg
     
Die Seite wird geladen...
Ähnliche Themen - Laufschrift läuft unsanft
  1. BigDundee
    Antworten:
    1
    Aufrufe:
    2.128