![]() |
Flickernder Newsticker - ich hab bald alle Techniken durch
Hallo Leute.
Ich sitz hier jetzt schon etliche Wochen an so einer besch...eidenen Newstickerfunktion, und irgendwie will es mir nicht gelingen. Aufgabe: einen String in Schriftgröße 72 vor rechts nach links durchscrollen lassen, nach möglichkeit Pixel für Pixel und die gleichmäßig, ohne Ruckeln, Flickern oder Sprünge. Der gesamte Zeichenbereich hat in etwa die Dimensionen von 1400 x 150 px. Es bleibt anzumerken dass der Newsticker nur ein Teilprogramm ist, und das restliche Programm auch ein bisschen Rechenleistung braucht. Damit ihr nicht denken müsst, ich frag hier einfach uns lass Euch die Arbeit schaffen, meine Verzeifelten versuche bisher: Begriffserklärung: Sprüge: Newsticker bewegt sich normalerweise um 1 px weiter, weil aber gerade etwas gerechnet wurde überspring der Newsticker mehrere Pixel oder wird alternativ langsamer. Flackern: Stellt Euch ein O oder eine Null vor, deren Oberseite nicht mehr an die Unterseite passt (versuche das mal zu illustrieren:) aus: ### #--# ### wird: ### -#--# -### Ruckeln: naja, wird bei "Sprünge" miterklärt (halt das Gegenteil davon), einfach ein unregelmäßiges Ablaufen) 1: ![]() Paintbox hilft nicht, und GD32 ist ab einer gewissen Größe auch recht langsam. 2: Bitmap mit Textout, BitBlt auf Backbuffer und dann BitBlt auf Form.Canvas, flackert auch 3: DirectX bzw. DirectDraw jeweils getestet mit ( ![]() 4: Einbinden eines TWebbrowsers mit einer Flash (SWF) Animation, die einen Newsticker darstellt - flackert auch 5: Testen einer Website, die mit DHTML und Javascript einen Text darstellt - flackert auch 6: Siehe 2, allerdings am Anfang den ganzen Text auf ein großes Bitmap, und dass dann immer um ein px verschoben mit BitBlt anzeigen lassen - ruckelt (<-- immernoch die beste Lösung bisher) Alle Methoden arbeiten mit Threads, da "Zeichen" wurde sowohl ohne, als auch mit Synchronize ausprobiert. Das Hauptproblem, weshalb Punkt 6 wohl auch am vielversprechensten aussieht, ist wohl dass die Schriften (Vektorgraphik!) jedesmal beim Textout-Zeichnen auf ein Bitmap neu skaliert und berechnet werden müssen (?). Hoffe das Problem selbst wird damit erstmal deutlich. Damit Ihr ein "bisschen" Anreiz habt mitzurätseln, stetze ich hiermit EINEN KASTEN BIER als BELOHNUNG aus (oder etwas vergleichbares nach eigener Wahl), wer maßgeblich zur Lösung dieses Problemes beiträgt! Vielen Dank schonmal im Vorraus, ich bin auf eure Antworten angewiesen. |
Re: Flickernder Newsticker - ich hab bald alle Techniken dur
also wenn dir das so wichtig ist, dass der da nicht springt, dann würde ich den gesamten berechnungskram in einen thread verlagern, den du alle sekunden anhältst, deinen ticker verschiebst, und dann wieder laufen lässt.
|
Re: Flickernder Newsticker - ich hab bald alle Techniken dur
Es existiert schon ein Thread für das Verschieben (ein Integer wird um 1 vermindet = X-Wert für Textout etc.). In einem anderen Thread wird die Draw-Routine (entweder die für DirectX oder die mit dem BitBlt) aufgerufen (während des Zeichnens ist der andere Thread suspended).
|
Re: Flickernder Newsticker - ich hab bald alle Techniken dur
ok, wie wärs mit timebased movement (also verschiebeung in abhängigkeit von tatsächlich vergangener zeit)? dann kanns zwar immer noch ruckeln, aber es sollte wenigstens nicht mehr irgendwie springen, zumindest je nach fps-zahl...
Dann kannst du dir auch den integer-verschiebe-thread sparen, da du nur on demand berechnest. (verschiebung in pixel = vergangene zeit in sek * verschiebung in pixel pro sek) Wenn du diesem thread, der also die verschiebung berechnet und zeichnet, eine höhere prio gibst, dann hilft das vielleicht.... Den thread am besten einmal starten und dann immer n sleep(100-500) reinhauen, damit er nicht dauernd zeichnet. |
Re: Flickernder Newsticker - ich hab bald alle Techniken dur
Also der Code geht bei mir relativ gut, auch bei 100% cpu - dann natürlich sehr langsam ;)
Delphi-Quellcode:
Mit GR32 ...
var
ende, x: Cardinal; begin ende := GetTickCount + 3000; x := 800; while GetTickCount < ende do begin PaintBox321.Buffer.Clear (clWhite32); PaintBox321.Buffer.Textout(x, 20, 'Hallo'); PaintBox321.Flush; sleep (0); if x <= 10 then x := 800 else dec (x); end; @Luke: Gerade dann wird es springen, wenn eine lange Zeit zwischen den Frames vergeht ;) |
Re: Flickernder Newsticker - ich hab bald alle Techniken dur
@jfheins: Das sieht generell schonmal ganz gut aus, (das obligatorische:) aaaber, mit steigender Schriftgröße (z.B. 150) und einem längeren Text (s.u.) wird der Ticker immer langsamer. Dann bleibt einem nur noch, die Schrittweite auf 2 oder Höher zu stellen, (dec(x, 2)) damit der Betrachter beim Lesen nicht einschläft. Und sobald die Schrittweite 2 beträgt, haben wir wieder diesen "Verzerrungseffekt" bzw. Flackern (hoffe Ihr könnt das nachvollziehen).
Meine aktuelle Version:
Delphi-Quellcode:
var
ende, x: Integer; begin ende := GetTickCount + 30000; x := 800; while GetTickCount < ende do begin PaintBox321.Buffer.Clear (clWhite32); PaintBox321.Buffer.Font.Size := 72; PaintBox321.Buffer.Textout(x, 0, 'Funktioniert das denn auch mit etwas längeren Texten noch flüssig und wenn die Schriftgröße 150 beträgt?'); PaintBox321.Flush; // sleep (0); Application.ProcessMessages; if x <= -50 then x := 800 else dec (x, 2); end; end; |
Re: Flickernder Newsticker - ich hab bald alle Techniken dur
Zeichne nicht direkt auf dem Canvas der Painbox, sondern auf ein Bitmap im Speicher, welches du dann mit BitBlt auf den Canvas kopierst. Zeichenroutinen sind unter Windows generell langsam.
|
Re: Flickernder Newsticker - ich hab bald alle Techniken dur
Nun gut, habe das ganze nun mit einen TBitmap32 als Hintergrundpuffer versucht, aber großartig (merkbar?) besser wird es auch nicht. Das Problem ist nach wie vor, dass es mit 1 Pixel je Takt echt ewig langsam ist und eine CPU Auslastung von 100% auf Dauer ist auch nicht wirklich ok. *seufz* Ich meine es gibt mittlerweile photorealistische super-3d computerspiele, das ist das Problem mit so einem blöden Text der einfach nur von rechts nach links durchlaufen soll (vor mir aus langen da 16 Farben die er darstellen kann).
Naja, aktueller Code, wobei ich denke dass wir vielleicht dennoch bei DirectX o.ä. besser aufgehoben wären: Danke nochmal an alle, die sich bisher an der Diskussion beteiligen, ich hoffe auf viele weitere Beiträge.
Delphi-Quellcode:
var
ende, x: Integer; begin ende := GetTickCount + 30000; x := 800; while GetTickCount < ende do begin backbuffer.Clear(clWhite32); backbuffer.Font.Size := 72; backbuffer.Textout(x, 0, 'Funktioniert das denn auch mit etwas längeren Texten noch flüssig und wenn die Schriftgröße 150 beträgt?'); BitBlt(PaintBox321.Canvas.Handle, 0, 0, width, 150, backbuffer.Canvas.Handle, 0, 0, SRCCOPY); // PaintBox321.Buffer.Clear (clWhite32); // PaintBox321.Buffer.Font.Size := 72; // PaintBox321.Buffer.Textout(x, 0, 'Funktioniert das denn auch mit etwas längeren Texten noch flüssig und wenn die Schriftgröße 150 beträgt?'); // PaintBox321.Flush; // sleep (0); // Application.ProcessMessages; if x <= -50 then x := 800 else dec (x); end; end; |
Re: Flickernder Newsticker - ich hab bald alle Techniken dur
|
Re: Flickernder Newsticker - ich hab bald alle Techniken dur
Hab bei dem Suchbegiff ScrollDC noch das folgende Thema ausgegraben
![]() Ich komm mit dem ScrollDC nicht so ganz klar. Wie geht das richtig?
Delphi-Quellcode:
var
ende, x: Integer; r: TRect; begin ende := GetTickCount + 30000; x := 800; while GetTickCount < ende do begin // Auf dem Canvas ist nun schon die aktuelle Schrift zu sehen r := Rect(0, 0, width, 150); ScrollDC(PaintBox321.Canvas.Handle, -1, 0, r, r, PaintBox321.Handle, NIL); // verschieben if x <= -50 then x := 800 else dec (x); end; Edit: Ich hab mit ScrollWindow eben ne kleine Demo geschrieben, und die sieht sau gut aus (mit nem Label). Die Sache ist, dass ja der Bereich, der vorher noch nicht sichtbar ist nun immer mit der letzten Pixelspalte des Labels gezeichnet wird (Labels scrollt links raus und hinterlässt eine Spur). Das muss man irgendwie mit dem ClipRect oder so machen. Wie genau Funktioniert das (* gleich mal "the fucking searchfunction"-benutzt* :D), für CodeBeispiele wäre ich ganz dankbar, ansonsten zeichne ich das vielleicht mit einem Bitmap und dann immer die letzte Pixelspalte, obwohl mit Label oder so schon lieber wäre.
Delphi-Quellcode:
repeat
ScrollWindow(Self.Handle, -1, 0, NIL, NIl); sleep(10); Application.ProcessMessages; until 1=2; |
Re: Flickernder Newsticker - ich hab bald alle Techniken dur
Zitat:
|
Re: Flickernder Newsticker - ich hab bald alle Techniken dur
Das ist zwar eine gute Idee (siehe mein Punkt 6), allerdings das du dann ein Problem, wenn du einen längeren Text bekommmst (sagen wir 10000 Zeichen, also widestring). Stell dir das mal als farbiges Bitmap vor mit 150px Höhe und ~10.000*50px = 500.000 px (!) Breite, das macht kein Arbeitsspeicher mit...
Irgendwer ein Beispiel für ScrollDC? |
Re: Flickernder Newsticker - ich hab bald alle Techniken dur
War Punkt 6 schon immer da oben :stupid: ? Bei langen Texten pufferst du einfach die doppelte (oder dreifache, ...) Bildbreite, das Neuberechnen verschiebst du optimalerweise in einen eigenen Thread.
|
Re: Flickernder Newsticker - ich hab bald alle Techniken dur
Hat noch keine mitr ScrollDC gearbeitet? Wie siehst mit ScrollWindow aus?
Edit: Mein aktuelle Code:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var ende, x: Integer; ScrollRect, ClipRect, UpdateRect: TRect; begin ende := GetTickCount + 30000; x := 0; while (GetTickCount < ende) and not cl do begin inc(x, 2); // backbuffer.Clear(clWhite32); // backbuffer.Font.Size := 72; // backbuffer.Textout(0, 0, 'Funktioniert das denn auch mit etwas längeren Texten noch flüssig und wenn die Schriftgröße 150 beträgt?'); // BitBlt(PaintBox321.Canvas.Handle, 0, 0, width, 150, backbuffer.Canvas.Handle, 0, 0, SRCCOPY); ScrollRect := PaintBox321.BoundsRect; ClipRect := PaintBox321.BoundsRect; ScrollDC(PaintBox321.Canvas.Handle, -2, 0, ScrollRect, ClipRect, 0, @UpdateRect); InvalidateRect(PaintBox321.Canvas.Handle,@updaterect,True); BitBlt(PaintBox321.Canvas.Handle, width-10, 0, 2, PaintBox321.Height, backbuffer.Canvas.Handle, x, 0, SRCCOPY); // ReleaseDC(Handle, PaintBox321.Canvas.Handle); // PaintBox321.Buffer.Clear (clWhite32); // PaintBox321.Buffer.Font.Size := 72; // PaintBox321.Buffer.Textout(x, 0, 'Funktioniert das denn auch mit etwas längeren Texten noch flüssig und wenn die Schriftgröße 150 beträgt?'); // PaintBox321.Flush; sleep (2); Application.ProcessMessages; // if x <= -50 then x := 800 // else dec (x, 2); end; end; |
Re: Flickernder Newsticker - ich hab bald alle Techniken dur
Delphi-Quellcode:
Der text wird nicht langsamer es dauer nur länger bis ein Buchstabe durchgescrollt ist weil er breiter ist. Es scheint also nur so als ob es langsamer wäre.
[quote="berens"]@jfheins: Das sieht generell schonmal ganz gut aus, (das obligatorische:) aaaber, mit steigender Schriftgröße (z.B. 150) und einem längeren Text (s.u.) wird der Ticker immer langsamer.
Die Geschwindigkeit muss also von der Schriftgrösse abhängig sein. Und das dann noch um "timebased movement" erweitern. Dann braucht man nur noch einen timer/Thread der 25 mal pro Sekunde aufgerufen wird. (Für die menschliche Wahrnehmung genügen ungefähr 25 Bilder pro Sekunde, um eine "ruckelfreie" Illusion der Kontinuität zu erzeugen" Wikipedia) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:11 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz