Textausgabe flimmert

Anfängerfragen zum Programmieren mit PureBasic.
EmmJott
Beiträge: 40
Registriert: 25.10.2024 12:23

Textausgabe flimmert

Beitrag 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?
Bin aktiv in der rentenvorbereitenden Arbeitslosigkeit - zwangsweise. Auch nach >30 Jahren im Betrieb springst Du über die Klinge, wenn der (Miss-)Manager seinen Hintern retten will. Lasst Euch von euren Arbeitgebern bloß nix von wegen Loyalität erzählen - wenn's drauf ankommt, ist die nix Wert!
Benutzeravatar
HeX0R
Beiträge: 3040
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win11 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2 + 3
Kontaktdaten:

Re: Textausgabe flimmert

Beitrag 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.
EmmJott
Beiträge: 40
Registriert: 25.10.2024 12:23

Re: Textausgabe flimmert

Beitrag 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?
Bin aktiv in der rentenvorbereitenden Arbeitslosigkeit - zwangsweise. Auch nach >30 Jahren im Betrieb springst Du über die Klinge, wenn der (Miss-)Manager seinen Hintern retten will. Lasst Euch von euren Arbeitgebern bloß nix von wegen Loyalität erzählen - wenn's drauf ankommt, ist die nix Wert!
Benutzeravatar
Olafmagne
Beiträge: 140
Registriert: 07.12.2017 17:30
Wohnort: Sete/Frankreich

Re: Textausgabe flimmert

Beitrag 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?
Unsinnige Anweisungen von Seiten des Chef's lösen grundsätzlich ein "Syntax Error" bei mir aus
OS=Linux Zorin
PureBasic 6.xx
Benutzeravatar
silbersurfer
Beiträge: 175
Registriert: 06.07.2014 12:21

Re: Textausgabe flimmert

Beitrag 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
Intel Quad Core 3,2 Ghz - GTX 1060 - BlitzBasic Plus 1.48 , PureBasic 5.70 LTS / Aktuelles Projekt PureCommander
Axolotl
Beiträge: 266
Registriert: 31.12.2008 16:34

Re: Textausgabe flimmert

Beitrag 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) 
Using PureBasic latest stable version and current alpha/beta (x64) on Windows 11 Home
EmmJott
Beiträge: 40
Registriert: 25.10.2024 12:23

Re: Textausgabe flimmert

Beitrag 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.
Bin aktiv in der rentenvorbereitenden Arbeitslosigkeit - zwangsweise. Auch nach >30 Jahren im Betrieb springst Du über die Klinge, wenn der (Miss-)Manager seinen Hintern retten will. Lasst Euch von euren Arbeitgebern bloß nix von wegen Loyalität erzählen - wenn's drauf ankommt, ist die nix Wert!
Benutzeravatar
mk-soft
Beiträge: 3845
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Textausgabe flimmert

Beitrag 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()
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Antworten