Grafikspeicher austausch ohne FlipBuffers()?

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
ne555
Beiträge: 24
Registriert: 12.01.2008 03:29

Grafikspeicher austausch ohne FlipBuffers()?

Beitrag von ne555 »

ich habe noch irgendwo einen Fehler und finde ihn nicht.
Für mein Projekt Multimeter-Visualisierung probiere ich rum, wie ich eine Trend-Kurve in einen Screen auf einem Fenster pixele.
Das Funktioniert soweit ganz gut, aber ich habe da einen komischen Effekt.
Beim 5 Programmdurchlauf tausch das Programm die Grafikinhalte des Screen-Feldes ohne das ich ein FlipBuffers() ausgelöst habe.

Den Code habe ich bis auf das nötigste reduziert. Das Phänomen tritt aber immer noch auf.
Was seht ihr im Programm:
Nachdem der Start-Button gedrückt wurde, werden drei Hilfslinien im Aufzeichnungstakt nach links verschoben.
Beim 5 Durchlauf wird ein leerer Screen eingeblendet.
Kommentiere ich die Zeilen
124 FlipBuffers()
und
126 ClearScreen()
aus, dürfte das Programm nur einen leeren Screen anzeigen. Aber beim 5 Durchlauf wird der Screen-Inhalt getauscht obwohl im ganzen Programm kein FlipBuffers mehr zu finden ist.
Wo ist der Wurm(Bug)?

cu ne555

Code: Alles auswählen

; Variablen deklaration
Global Start.b = 0
Global Stop.b  = 1

StartTime.l  = 0
StopTime.l   = 0
Timer.l      = 0
StartTimer.l = 0
Zaehler.l    = 0
test.l       = 0
Time.s       = FormatDate("%dd:%mm:%yyyy:%hh:%ii:%ss", Date()) ; aktuelle Zeit auslesen
Timeref.s    = Time
a.l          = 0
AusZeit.l    = 2000

Global Plot_X.l = 0
Global Plot_Y.l = 0
ZA1.l            = 0
ZA2.l            = 0

Structure XY
  X.l
  Y.l
EndStructure

Structure xy_trend
 x_trend.l
 y_trend.l
 index_trend.l
EndStructure
 
  
Global Dim Trend.XY_trend(418)
Global NewList XY_list.XY()
Global X.l          = 0
Global Y.l          = 0
Global index_xy.l   = 0
Global MW1_Plot.l   = 0
Global MW2_Plot.l   = 0
Global Zeitstemp.l  = 0
Global SIM          = 1
Global zahler       = 0 
Global Richtung     = 0   
; String-Variablen
Global Bereich.s      ="" ; Messbereich (Temperatur, Volt, Ampere)
Global Messwert1.s    =""
Global Messwert2.s    =""
Global Pol.s          ="" ; Vorzeichen / Polarität des Messwerts (+ -)
Global MA.s           =""
Global MessString.s   ="TE  0022    +" ;String wie er von Messgerät gesendet wird
Global MessStringZW.s =""
Datum.s   = Left(Time, 10)
Uhrzeit.s = Right(Time, 8)

Global testv.l
;Konstanten
#Start            = 1
#Stop             = 2
#Messabfrage      = 3
#Beenden          = 4


Global test_a.l = 419  ; Startpunkte Trend Hilfslinien
Global test_b.l = 280
Global test_c.l = 141




Procedure MessStr()
If SIM = 1
   X = X + 1
   index_xy = index_xy + 1
   If Richtung = 0
      Y = Y + 1
      If Y >=91
         Richtung = 1
      EndIf
   EndIf
   If Richtung = 1
      Y = Y - 1
      If Y <= 50
         Richtung = 0
      EndIf
   EndIf
 EndIf              



EndProcedure

Procedure Plot_XY()


 StartDrawing(ScreenOutput())
  
; Hilfslinien        
    If test_a < 0 
        test_a = 419
       Else
        test_a = test_a - 1
    EndIf  
    
    
    If test_b < 0
        test_b = 419
     Else
        test_b = test_b -1
    EndIf        
   
    If test_c < 0
        test_c = 419
     Else
        test_c = test_c -1
    EndIf         
         
     Line (test_a ,0,0,300,$0000FF)
     Line (test_b ,0,0,300,$00FF00)
     Line (test_c ,0,0,300,$FF0000)
     

  StopDrawing()
  
  FlipBuffers(0)
  
  ClearScreen(RGB($00,$00,$00))
  
 EndProcedure


; Hauptprogramm
 If InitSprite() = 0
     MessageRequester("Error", "Problem bei der Screen/Sprite initialisierung",0)
 EndIf    
 If OpenWindow(0,100,100,640,480,"Mess-Wert-Erfassug",#PB_Window_SystemMenu|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget)
      
     CreateGadgetList(WindowID(0))
     ButtonGadget(#Start,20,170,100,20,"Start")
     GadgetToolTip(#Start,"Aufzeichnung starten")
     ButtonGadget(#Stop,20,210,100,20,"Stop")
     GadgetToolTip(#Stop,"Aufzeichnung stoppen")
     ListViewGadget(#Messabfrage,10,390,260,80)
     ButtonGadget(#Beenden,20,290,100,20,"Beenden")
     GadgetToolTip(#Beenden,"Programm beenden")

     OpenWindowedScreen(WindowID(0),215,5,420,300,0,0,0)
 EndIf
 
    
  Repeat ; begin Hauptschleife
  
    Time  = FormatDate("%dd:%mm:%yyyy:%hh:%ii:%ss", Date()) ; aktuelle Zeit auslesen
    
    EventID = WaitWindowEvent(1)
      If EventID = #PB_Event_CloseWindow ; Auf Seite schließen abfragen 
         Quit = 1
      EndIf
      
      If EventID = #PB_Event_Gadget ; Auf Event abfragen

      
         If Stop = 1  ; Auf Button Start abfragen
            If EventGadget() = #Start
               Start      = 1
               Stop       = 0
               ;Hcom = ComOpen(MyCom,0,255,255) ; öffnen der Com Schnittstelle
               AddGadgetItem(#Messabfrage,Richtung,"Starte Aufzeichnung          :" + Time) 
               If Richtung = -1
                  Richtung = 1
               EndIf    
            EndIf
         EndIf  
        
       If Stop = 0 ; Auf Button Stop abfragen
          If EventGadget() = #Stop
             Start      = 0
             Stop       = 1
             Zaehler    = 0
             StartTimer = 0
             AddGadgetItem(#Messabfrage,1,"Aufzeichnung beendet      :" + Time)
          EndIf
       EndIf 

        If EventGadget() = #Beenden ; Auf Button beenden abfragen
           If Start = 1
              AusZeit = 2000
            Else
              AusZeit = 1
           EndIf      
           AddGadgetItem(#Messabfrage,1,"Aufzeichnung beendet      :" + Time) 
           Ende  = 1
        EndIf
     EndIf ; ende auf Event abfragen
      
      If Start = 1 ; Polling intervall
         If StartTimer = 0
            StartTime  = ElapsedMilliseconds()
            StopTime   = StartTime + 1000
            StartTimer = 1
         EndIf
         If StartTimer = 1
            StartTime  = ElapsedMilliseconds()
            If StartTime >= StopTime  
               MessStr()
               AddElement(XY_list())
               XY_list()\X = X
               XY_list()\Y = Y
               If index_xy < 417
                  AddGadgetItem(3,1," "+ MessStringZW + "     X= "+Str(X) + "   /   Y= "+Str(Y) + "   Index: "+Str(index_xy))
                Else
                  AddGadgetItem(3,1," "+ MessStringZW + "     X= "+Str(Trend(417)\x_trend) + "   /   Y= "+Str(Y) + "   Index: "+Str(index_xy))
               EndIf
               StartTimer = 0
               Plot_XY(); Trend Pixeln
            EndIf  
         EndIf
     EndIf ;ende polling
     
     If Ende = 1  ; Reaktion auf Beenden-Button (mit Aufzeichnung beenden)
        test  = test + 1
        If test = 3
           Quit = 1
           Ende = 0
           test = 0
        EndIf   
     EndIf
        
 
   Until Quit=1  ; Hauptschleife beenden
Delay(AusZeit)   ; Verzögerung bei Programm-Ende
End

[/code]
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

ich blicke bei deinem code nicht ganz durch.
du verwendest irgendwie doppelte Flags Start + Stop und dann noch StartTimer,
und zwei timer StartTime + StopTime...
also irgendwie doppelt gemoppelt...
deine Screen-Ausgabe springst du irgendwann in einer Bedingung an,
das ist auch etwas unübersichtlich.

das ist aber eigentlich deine sache, das soll nur verdeutlichen,
dass ich nicht die Geringste Spur habe, wo die Ursache liegen könnte...

Abhilfe hingegen habe ich:
wenn man das Clearscreen an den Anfang der Procedure stellt,
wo es eigentlich auch hingehört,
dann tritt der 5tes-Bild-Aussetzer nicht auf.

also

Code: Alles auswählen

Procedure Plot_XY()

 ClearScreen($000000)

 StartDrawing(ScreenOutput())
; Hilfslinien       
    If test_a < 0
        test_a = 419
       Else
        test_a = test_a - 1
    EndIf 
    If test_b < 0
        test_b = 419
     Else
        test_b = test_b -1
    EndIf       
    If test_c < 0
        test_c = 419
     Else
        test_c = test_c -1
    EndIf         
     Line (test_a ,0,0,300,$0000FF)
     Line (test_b ,0,0,300,$00FF00)
     Line (test_c ,0,0,300,$FF0000)
  StopDrawing()
 
  FlipBuffers(0)
 
 EndProcedure
btw: wenn du sowieso Hex-Zahlen verwendest, kannst du dir die RGB-Funktion auch sparen... ;)
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
ne555
Beiträge: 24
Registriert: 12.01.2008 03:29

Beitrag von ne555 »

Erst einmal vielen Dank, so geht’s.:allright:

In den Beispielen der Hilfe wird das ClearScreen auch immer direkt nach FlipBuffers gesetzt.
Logisch sehe ich da auch keinen Unterschied.
Aber egal...

Den Code habe ich noch nicht überarbeitet ;-)
Mir geht’s erst mal nur um die Funktion.
du verwendest irgendwie doppelte Flags Start + Stop und dann noch StartTimer,
Die Start/Stop Flags werden über die Buttons gesetzt. Ich komme aus der SPS Programmierung. Da arbeite ich gerne mit sich gegenseitig verriegelnden Variablen.
Bloß nicht starten wenn irgendwo noch eine Stopbedingung erfüllt ist 
Die ElapsedMilliseconds() Funktion für einen Timer zu benutzen, ist bestimmt nicht die eleganteste Art so etwas zu machen. Aber es ist die einzige Funktion, die in der Hilfe dazu beschrieben wird. Den Timer macht man sich damit dann ja auch selber.

Der Timer ist doch ganz einfach:

Code: Alles auswählen

If Start = 1 ; Polling intervall 	  ; Wurde eine Aufzeichnung gestartet? 
If StartTimer = 0 			    ; Läuft der Timer ? (verhindert ein              
                                                    ;Überschreiben. im nächsten             
                                                    ;Programm-Zyklus
 StartTime  = ElapsedMilliseconds()  ; speichert eine Millisekunden-Wert in       
                                                    ;StartTime
 StopTime   = StartTime + 1000        ; Addiert 1000 Ms auf den Startwert
 StartTimer = 1	                              ; ist Var = 1 dann sind die 1000 MS 
                                                     ;noch nicht vergangen 
EndIf 
If StartTimer = 1		       ; wurde Vergleichwert schon bestimmt? 
 StartTime  = ElapsedMilliseconds()	;die Var. hat oben ihre Schuldigkeit 
                                                        ;getan und kann von 
                                                       ;neuem benutzt werden um einen  
                                                       ;aktuellen ;Millisekundenwert zu 
                                                       ;ermitteln, und zwar bei jedem ;
                                                        ;Prog.-Zyklus  
If StartTime >= StopTime	;vergleicht den aktuellen Millisekundenwert 
                                             ;mit dem Ermittelten + 1000 Ms, ist der 
                                             ;aktuelle Wert um min. 1000 Ms größer als 
                                             ;der oben ermittelte Startwert, dann
  MessStr()				;Procedureaufruf 
 StartTimer = 0 		      ; Der Timer kann im nächsten Zyklus 
                                             ;wieder neu beschrieben werden
  Plot_XY()				; Trend Pixeln 
 EndIf  
EndIf 
EndIf ;ende polling
Ich hoffe ich habe das nicht zu umständlich gemacht, aber in der Hilfe habe ich keine andere Möglichkeit gefunden.

viele Grüße ne555
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

nen timer funktioniert auch einfacher:

Code: Alles auswählen

; Init
#TimerStep = 1000
Timer = ElapsedMilliseconds() + #TimerStep

; in der Schleife
TimerEvent = 0
If Timer <= ElapsedMilliseconds()
  Timer + #TimerStep
  TimerEvent = 1
EndIf
...du brauchst keine zweite variable zum rückspeichern... ;)
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
ne555
Beiträge: 24
Registriert: 12.01.2008 03:29

Beitrag von ne555 »

Danke !!
deshalb bin ich hier.....
Meine Lösungen funktionieren zwar, aber effizientes Programmieren ist anders

Grüße aus Bielefeld
ne555
Antworten