Seite 1 von 1
Textausgabe flimmert
Verfasst: 07.11.2024 11:44
von EmmJott
Hallo,
habe das Problem, dass Textausgaben "flimmern", wenn die Änderungen zu schnell sind. Beispiel:
Code: Alles auswählen
parent = OpenWindow(#PB_Any, 0, 0, 500, 100, "", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
csb = CreateStatusBar(#PB_Any, WindowID(parent))
If csb
AddStatusBarField(#PB_Ignore)
EndIf
For i = 0 To 50000
StatusBarText(csb, 0, "Zähler = "+Str(i))
Next
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
End
EndSelect
ForEver
Der Text der Statusbar wird wohl zu schnell geändert, wohl schneller, als der Monitor anzeigen kann. Zeitweise sieht man also gar keinen Text, oder nur schemenhaft. Kann man die Anzeige verbessern, ohne dass die Ausführungsgeschwindigkeit nennenswert reduziert wird?
Re: Textausgabe flimmert
Verfasst: 07.11.2024 11:53
von HeX0R
Du solltest Dich evtl. mal mit dem Windows Eventhandling beschäftigen.
Was Du hier machst, ist 50000 Events in die Warteschlange pushen (währenddessen zeigt Deine Statusbar übrigens gar nix an!), aber erst danach werden die mühsam da wieder herausgezogen und verarbeitet.
Re: Textausgabe flimmert
Verfasst: 07.11.2024 12:49
von EmmJott
Hi,
also, bei mir zeigt es während des Ablaufs schon was an, nur halt wie beschrieben: zeitweise flimmernd und/oder schemenhaft. Natürlich ist das Beispiel Mist, wollte den Effekt ja auch nur mal veranschaulichen, wo doch ein Bild mehr als 1000 Worte sagt (angeblich). Deswegen bitte nicht zu sehr an dem Beispiel festhalten, sondern eher an der Sache "Ausgabe schneller als Monitor" - wenn ich mit dieser Vermutung überhaupt richtig liege.
Edit:
Kann es sein, dass StatusBarText vielleicht auch nur eine vergleichsweise langsame Textausgabe ist und andere Möglichkeiten das schneller darstellen könnten?
Re: Textausgabe flimmert
Verfasst: 07.11.2024 14:10
von Olafmagne
Der Computer könnte die Ausgaben schon schaffen,
ABER:
der Text muss auch auf den Bildschirm,
und wie HeXor schon schrieb, 50000 Änderungen in
ein paar Millisekunden ist für den Monitor doch schon etwas zu viel!
Ausserdem, Überlege mal::
wie hoch ist die Bildschirmfrequenz?
gleich oder höher wie die Zeit, die deine Schleife braucht?
Sicher nicht!
Also, deine Ausgabe ist schneller,wie des Monitors Vermögen.
Wenn du, zB 5 Wörter in der Sekunde schreiben kannst und jemand 50 Wörter/sec diktiert,
kannst du dann alles in der Diktiergeschwindigkeit schreiben?
Re: Textausgabe flimmert
Verfasst: 07.11.2024 17:11
von silbersurfer
Moin EmmJott, ich würde es mit einen Timer lösen. Ich kenne das bestehende Problem mit dem Flimmern hier dein Beispiel wie es dann nicht Flimmert
Code: Alles auswählen
parent = OpenWindow(#PB_Any, 0, 0, 500, 100, "", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
csb = CreateStatusBar(#PB_Any, WindowID(parent))
If csb
AddStatusBarField(#PB_Ignore)
AddStatusBarField(#PB_Ignore)
AddStatusBarField(#PB_Ignore)
EndIf
;Timer setzen
AddWindowTimer(parent, 100,60)
Repeat
Select WaitWindowEvent()
Case #WM_MOUSEMOVE
move=move+1
Case #PB_Event_Timer
;hier die Zeitkritschen sachen abfragen
Time$ = FormatDate("%hh:%ii:%ss", Date())
i=i+1
If EventTimer() = 100
StatusBarText(csb, 0, "Zähler = "+Str(i))
StatusBarText(csb, 1, "Mausbewegen = "+Str(move))
StatusBarText(csb, 2, "Zeit = "+Time$)
EndIf
Case #PB_Event_CloseWindow
End
EndSelect
ForEver
Re: Textausgabe flimmert
Verfasst: 07.11.2024 18:01
von Axolotl
Hier noch eine Thread basierte Lösung:
Ich habe mal unterstellt, dass der Prozess schon so schnell wie möglich abgearbeitet werden soll.
Also die Schleife (der wirkliche Prozess) wird in einen Thread ausgelagert.
Mit Hilfe eines Timers wird immer mal wieder (siehe Timeout Werte) der aktuelle Zählerstand angezeigt.
Den Rest findest Du vllt. selbst heraus.
Code: Alles auswählen
EnableExplicit
Global parent, csb
Structure TThread
Counter.i
;
Thread.i
bTerminate.i
EndStructure
Global ThreadParam.TThread
Procedure Counter_WorkerThread(*Param.TThread)
Protected i
Debug #PB_Compiler_Procedure + " start "
For i = 0 To 50000
*Param\Counter = i
Delay(1)
If *Param\bTerminate = #True
Debug #PB_Compiler_Procedure + " say good bye "
Break
EndIf
Next
Debug #PB_Compiler_Procedure + " done "
EndProcedure
parent = OpenWindow(#PB_Any, 0, 0, 500, 100, "", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
csb = CreateStatusBar(#PB_Any, WindowID(parent))
If csb
AddStatusBarField(250)
AddStatusBarField(#PB_Ignore)
EndIf
; For i = 0 To 50000
; StatusBarText(csb, 0, "Zähler = "+Str(i))
; Next
ThreadParam\Thread = CreateThread(@Counter_WorkerThread(), @ThreadParam)
AddWindowTimer(parent, 0, 10) ; fastest possible interval
AddWindowTimer(parent, 1, 50) ; this is flickerfree on my computer
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
ThreadParam\bTerminate = #True
If WaitThread(ThreadParam\Thread, 3000) = 0
Debug "Kill thread now...."
KillThread(ThreadParam\Thread)
EndIf
Break ; End
Case #PB_Event_Timer
Select EventTimer()
Case 0
StatusBarText(csb, 0, "Zähler = " + Str(ThreadParam\Counter))
Case 1
StatusBarText(csb, 1, "Zähler = " + Str(ThreadParam\Counter))
EndSelect
EndSelect
ForEver
RemoveWindowTimer(parent, 0)
RemoveWindowTimer(parent, 1)
Re: Textausgabe flimmert
Verfasst: 08.11.2024 18:25
von EmmJott
Hallo @ all,
vielen Dank für euren Input. An einen Timer hatte ich mittlerweile auch schon gedacht. Es macht auch kaum Sinn, für den User einen Wert darzustellen, den der User gar nicht sehen kann, da sich der Wert zu schnell ändert. Ab 30 Bilder / sec. würde es quasi ein Film ...
Meine Überlegungen sind aktuell, entweder in gewissen Zeitabständen den dann erreichten Wert darzustellen, oder alle 50 (oder 100 oder ...) Wertänderungen den aktuellen Wert auszugeben, was sich vielleicht auch günstig auf die Ablaufgeschwindigkeit auswirkt.
Re: Textausgabe flimmert
Verfasst: 09.11.2024 13:01
von mk-soft
Vielleicht hilft dieses mit Thread und stabilen Event Loop
Update
Code: Alles auswählen
;-TOP by mk-soft, v1.02.1, 10.11.2024, Thread example
Enumeration CustomEvent #PB_Event_FirstCustomValue
#MyEvent_Status
EndEnumeration
Enumeration 1
#thStart
#thDone
#thCancel
#thCounter
EndEnumeration
Structure udtWorkData
ThreadID.i
State.i
Cancel.i
Counter.i
EndStructure
Global thData.udtWorkData
Procedure thWork(*Data.udtWorkData)
With *Data
PostEvent(#MyEvent_Status, 0, 0, #thStart)
; Vorbereichtung
\State = #thStart
\Counter = 0
\Cancel = 0
; Loop
While \Counter < 1000000
; Abfrage thread abbechen
If \Cancel
Break
EndIf
; Verarbeitung
\Counter + 1
If \Counter % 1000 = 0 ; Modula 1000
PostEvent(#MyEvent_Status, 0, 0, #thCounter, \Counter)
; Save CPU Power
Delay(10)
EndIf
Wend
If \Cancel
PostEvent(#MyEvent_Status, 0, 0, #thCancel)
;Verarbeitung abbruch
\State = #thCancel
Else
PostEvent(#MyEvent_Status, 0, 0, #thDone)
;Verarbeitung beenden
\State = #thDone
EndIf
; Zum schluß die ThreadID löschen. Es könnte ein andere Thread die ID wieder verwenden
\ThreadID = -1 ; Auf ungültige ID setzen. Bei Null kann der Debugger bei Abfrage ein Error auslösen.
EndWith
EndProcedure
; ----
Procedure UpdateWindow()
Protected dx, dy
dx = WindowWidth(0)
dy = WindowHeight(0) - StatusBarHeight(0) - MenuHeight()
; Resize Gadgets
EndProcedure
Procedure Main()
Protected dx, dy
#WinStyle = #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget
If OpenWindow(0, #PB_Ignore, #PB_Ignore, 600, 400, "Test Window", #WinStyle)
; MenuBar
CreateMenu(0, WindowID(0))
MenuTitle("&File")
MenuItem(1, "&Start")
MenuItem(2, "&Cancel")
MenuBar()
MenuItem(99, "E&xit")
; StatusBar
CreateStatusBar(0, WindowID(0))
AddStatusBarField(120)
AddStatusBarField(200)
AddStatusBarField(#PB_Ignore)
; Gadgets
dx = WindowWidth(0)
dy = WindowHeight(0) - StatusBarHeight(0) - MenuHeight()
; Bind Events
BindEvent(#PB_Event_SizeWindow, @UpdateWindow(), 0)
; Main Loop
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Select EventWindow()
Case 0
If IsThread(thData\ThreadID)
r1 = MessageRequester("Achtung!", "Thread läuft noch! Abbrechen?", #PB_MessageRequester_YesNo | #PB_MessageRequester_Warning)
If r1 = #PB_MessageRequester_Yes
If IsThread(thData\ThreadID)
thData\Cancel = #True
If WaitThread(thData\ThreadID, 5000) = 0
KillThread(thData\ThreadID)
EndIf
EndIf
Break
EndIf
Else
Break
EndIf
EndSelect
Case #PB_Event_Menu
Select EventMenu()
Case 1
If Not IsThread(thData\ThreadID)
thData\ThreadID = CreateThread(@thWork(), @thData)
EndIf
Case 2
If IsThread(thData\ThreadID)
thData\Cancel = #True
EndIf
Case 99
PostEvent(#PB_Event_CloseWindow, 0, 0)
EndSelect
Case #PB_Event_Gadget
Select EventGadget()
EndSelect
Case #MyEvent_Status
Select EventType()
Case #thStart
StatusBarText(0, 0, "Start ...")
Case #thDone
StatusBarText(0, 0, "Done.")
Case #thCancel
StatusBarText(0, 0, "Cancel")
Case #thCounter
StatusBarText(0, 1, Str(EventData()))
EndSelect
EndSelect
ForEver
EndIf
EndProcedure : Main()