German Activity_touch Puffer löschen

Skywalker

Member
Licensed User
Longtime User
Hallo,

stehe vor folgenden Problemund finde die Lösung nicht.

Es wird eine Grafik auf einem Canvas gezeichnet, welche am Ende auch mit dem Finger verschoben werden kann.
Damit dies nicht während des Zeichnes geschehen kann, frage ich in der "activity_touch" über eine Variabel ab, ob gerade die Grafikausgabe stattfindet.
Falls ja, wird die Subroutine direkt wieder verlassen und gut ist.
Aber, die ganzen Gesten werden sich wohl in einem Puffer gemerkt und so passiert es, das nach Fertigstellung der Grafikausgabe diese alle abgearbeitet werden.
Folge, die Grafik spring hin und her.

Ich suche nun eine Möglichkeit, diesen Puffer zu löschen, bzw. es irgendwie anders hin zu bekommen.

Gruß
Sky

Edit:
In der Loop, welche die Grafik auf dem Canvas ausgibt, befindet sich ein "Invalidate" und ein "DoEvents".
Ansonsten wird mir die Grafik erst nach Ablauf der Loop angezeigt.
Ich denke hier liegt das Problem, aber anders bekomme ich momentan kein Update des Bildschirms hin.
 
Last edited:

Skywalker

Member
Licensed User
Longtime User
Code Posten ist jetzt etwas schwierig, bin auf der Arbeit.
Grafik wird aber mit Canvas auf einem Panel ausgegeben.
Das sieht in etwa so aus.

Sub Activity_Resume()
...
Berechnung_Aktiv = True
For i = 0 to irgendwas
.. Jede Menge Berechnungen
Canvas1.DrawLine(x,y,...usw.)
Panel1.Invalidate
DoEvents
next i
Berechnungen_Aktiv = false
End Sub

Sub Activity_Touch(x,y,Action...usw)
If Berechnungen_Aktiv = True then Return True
Select Action
...
EndSelect
Return True
End Sub

Während der Berechnung und Grafikausgabe soll also kein Touch abgearbeitet werden, das funktioniert auch. Aber alle Touch-Events werden nach der Grafikausgabe abgearbeitet. Das soll aber nicht sein.
Denke es liegt an DoEvents. Lass ich das aber weg, wird die Grafik erst nach Fertigstellung angezeigt. Genauso ist es mit dem Panel1.Invalidate.
Habe es dann ohne DoEvents probiert und anstelle dessen ein Panel1.Invalidate(Rect) eingefügt, aber auch dann wird die Grafik erst nach Ablauf der For-Schleife angezeigt.
 

klaus

Expert
Licensed User
Longtime User
Zuerst schon mal, diese Zeile:
B4X:
Next i
muss so aussehen:
B4X:
Next
Die Incrementvariable darf nicht hinter Next stehen.

Um heauszufinden wo das Problem liegt schlage ich Dir vor eine globale Variable j zu erstellen und diese in der Schleife gleich i zu setzen.
In der Touch Routine setze zwei Log rein. Dann kannst Du sehen was in der Touch Routine passiert.
B4X:
Sub Activity_Touch(Action As Int, X As Float, Y As Float)
  Log("1 " & j)
  If Berechnungen_Aktiv = True Then Return
  Log("2 " & j)  
  Select Action
   ...
  EndSelect
End Sub
Die Activity_Touch Routine braucht keine boolsche Variable nach Return nur Panel_Touch Routinen braucht sie.

Beste Grüsse.
 
Last edited:

Skywalker

Member
Licensed User
Longtime User
Danke Klaus.
Das mit dem "Next" ist mir bekannt. Hatte heute das Code-Beispiel aus dem Kopf heraus geschrieben.
Dein Vorschlag mit den Variabeln hilft mir nicht weiter. Was in der Touch-Routine passiert ist mir schon klar. Daran liegt es nicht.

Wie schon geschrieben, solange die Schleife mit der Grafikausgabe beschäftigt ist, wird jede Fingergeste in der Touch-Routine ignoriert,
durch "If Berechnungen_Aktiv = True then Return". Das ist ja auch so gewollt.

Nur, sobald die Schleife durch ist und die Grafik somit fertig, werden alle Gesten ,die während der Grafikausgabe getätigt wurden, abgearbeitet.
Also sind die Gesten irgendwie gepuffert worden. Das soll aber so nicht sein.
 

klaus

Expert
Licensed User
Longtime User
Dein Vorschlag mit den Variabeln hilft mir nicht weiter. Was in der Touch-Routine passiert ist mir schon klar. Daran liegt es nicht.

Wie schon geschrieben, solange die Schleife mit der Grafikausgabe beschäftigt ist,
Bist Du sicher ? Hast Du es ausprobiert ob die Touch Routine aufgerufen wird wenn die Schlaufe durchlaufen wird ? Das wollte Ich mit den Log Schlüsselworten ausprobieren.
Es kommt mir komisch vor dass die Routine aufgerufen wird und nachher noch einmal. Ich vermute nàhmlich dass die Routine nicht aufgerufen wird so lange das Programm in der Schlaufe ist, und die Touch-Events in einer Warteschlange bleiben.
Ohne den Code kann Ich da leider nicht weiter suchen.

Beste Grüsse.
 

Skywalker

Member
Licensed User
Longtime User
Während der Schleife wird die Touch_Routine nicht abgearbeitet. Höchstens einmal am Anfang. Habe das mit der Variabel getestet.
Erst wenn die Schleife durch ist, wird der Puffer (Warteschlange) abgearbeitet.

Das bedeutet natürlich, das ich während des Schleifendurchlaufes in der Touch_Routine den Puffer nicht löschen könnte. Weil da ja noch nichts abgefragt wird.
Wie kann ich diese Warteschlange nun umgehen?
 

klaus

Expert
Licensed User
Longtime User
Eigentlich müsste DoEvents die Touch Routine aufrufen lassen.

Versuche es mal mit einem Timer:
- Am Ende der Schlaufe setze einen Timer1.Enabled = True

- In der Timer1_Tick Routine
- Timer1.Enabled = False
- Berechnungen_Aktiv = False

Während der Timerzeitspanne werden die Touchevents aufgerufen,
aber da die Berechnungen_Aktiv Variable immer noch False ist wird nichts durchgeführt.
Die Länge der Zeitspanne des Timers musst Du ausprobieren.

Ist bestimmt nicht die eleganteste Lösung sollte aber funktionieren, habe es nicht ausprobiert.

Beste Grüsse.
 
Last edited:

Skywalker

Member
Licensed User
Longtime User
Habe das mit dem Timer ausprobiert. Leider bleibt alles beim alten.

[EDIT]
Habe den Timer wieder raus genommen und festgestellt, das manchmal wohl doch die Touch-Routine aufgerufen wird.
 
Last edited:

Skywalker

Member
Licensed User
Longtime User
Glaube, ich ich komme der Ursache näher.

Innerhalb der Berechnungsroutine gibt es zwei For-Schleifen.
Die mittlere dauert länger und es werden keine Events abgearbeitet.

Also sieht in etwas so aus:
B4X:
Sub Activity_Resume()
 Berechnung_Aktiv = True
 For i = 0 to irgendwas
   ...ein paar Berechnungen
      For ii = 0 to irgendwas2
         .. Jede Menge Berechnungen
         Canvas1.DrawLine(x,y,...usw.)
      next  
   Panel1.Invalidate
   DoEvents
 next i
Berechnungen_Aktiv = false
End Sub

Setze ich jetzt Invalidate und DoEvents ans Ende der mittleren Schleife, werden die Touch-Events wohl eher abgearbeitet.
B4X:
Sub Activity_Resume()
 Berechnung_Aktiv = True
 For i = 0 to irgendwas
   ...ein paar Berechnungen
      For ii = 0 to irgendwas2
         .. Jede Menge Berechnungen
         Canvas1.DrawLine(x,y,...usw.)
         Panel1.Invalidate
         DoEvents
      next  
 next i
Berechnungen_Aktiv = false
End Sub

Problem ist nur, das die Berechnung der Grafik dann extrem lange dauert.
 

klaus

Expert
Licensed User
Longtime User
Ja, die zweite Schlaufe war in Deinem Beispielcode nicht dabei.
Um die Berechnung zu beschleunigen schlage Ich Dir folgenden Kompromiss vor.
B4X:
Sub Activity_Resume
    Dim i, ii As Int
    
    Berechnung_Aktiv = True
    For i = 0 To irgendwas
        '...ein paar Berechnungen
        For ii = 0 To irgendwas2
            '.. Jede Menge Berechnungen
            Canvas1.DrawLine(x,y,...usw.)
            DoEvents
        Next  
        Panel1.Invalidate
    Next
    Berechnung_Aktiv = False
End Sub
Beste Grüsse.
 

Skywalker

Member
Licensed User
Longtime User
Danke, das hatte ich auch versucht.
Die Berechnung dauert dann aber immer noch 50% länger als normal und die Gesten
werden zum Teil trotzdem erst am Ende abgearbeitet.

Hat alles keinen Sinn. Ich brauche eine Lösung um die Warteschlange zu löschen oder Abzuarbeiten ohne das die Berechnung neu startet.
Es ist wohl so, das der Puffer erst komplett nach Ende der "Sub Activity_Resume" abgearbeitet wird.
Denn ich habe z.B. folgendes versucht, aber die Warteschlange wird nicht gelöscht.
B4X:
Sub Activity_Resume
    Dim i, ii As Int
    
    Berechnung_Aktiv = True
    For i = 0 To irgendwas
        '...ein paar Berechnungen
        For ii = 0 To irgendwas2
            '.. Jede Menge Berechnungen
            Canvas1.DrawLine(x,y,...usw.)
        Next  
      Panel1.Invalidate
      DoEvents
    Next

    For a = 0 to 50   '<=
     DoEvents          '<=
    Next                 '<=
    Berechnung_Aktiv = False
End Sub
 

Roeschti

Member
Licensed User
Longtime User
Also wenn ich's richtig verstanden hab' malst du auf ein Panel via eine Leinwand (Canvas) und nur die erste / letzteVerschieberei soll anhand eines Touch Events stattfinden, richtig?

Warum fragst du dann nicht den Panel Touch Event statt Activity Touch Event?
Du könntest das Panel während der Rechnerei verstecken, verkleineren, deaktvieren, was anderes darüber legen oä, so dass gar keine neuen Touch Ereignisse ausgelöst werden.

Actitiy Touch Events werden vom OS in einer Queue behandelt, dann ran zu kommen ist wohl extrem schwer.
 

Skywalker

Member
Licensed User
Longtime User
Habe die Touch_Routine etwas geändert und dann funktioniert es einwandfrei im Emulator, aber nicht am Gerät.

@Roeschti

Im eigentlichem Programm frage ich schon das Panel Touch Event ab.
Die Idee mit dem Deaktivieren des Panels1 ist aber super.
Auch das funktioniert im Emulator bestens, aber nicht am Gerät.
Sobald die Berechnungsroutine beendet ist, arbeitet das Gerät die Warteschlange trotzdem ab.
Am Emulator passiert nichts.

Das ist doch nicht normal.
 

Skywalker

Member
Licensed User
Longtime User
So Leute ich habe euch mal ein Beispiel gebastelt.
Es ist nicht das eigentliche Programm um das es geht, aber hier passiert genau das gleiche.

Es werden einige Kreise auf einem Canvas gezeichnet, Das Panel ist während dieser Zeit deaktiviert.
Folgendes nun bitte ausprobieren
- Nach dem Start über den Bildschirm Wischen. Es sollte nichts passieren, die Grafik wird fertig gezeichnet und das Programm bleibt stehen. Gut!

- Steht unten "Fertig", dann nach links oder rechts wischen und die Grafik wird neu gezeichnet. Auch gut

- Dann während der Grafikausgabe mehrmals einige Gesten ausführen. Diese werden dann plötzlich nacheinander abgearbeitet. Das ist schlecht, denn das soll nicht so sein.

- Ganz merkwürdig ist, wenn man auf "Reset" klick, werden die Gesten nicht aus dem Puffer abgespielt.
 

Attachments

  • CanvasTest.zip
    2 KB · Views: 291
Last edited:

Roeschti

Member
Licensed User
Longtime User
Nee, funktioniert wie es soll, auf'm Emulator wie auf dem Gerät. Es wird immer nur eine Geste ausgeführt, egal ob ich während dem Zeichnen rumfummle oder nicht, sie werden bei mir weder gepuffert noch sonst was.

Ich kann zB von links nach rechts wischen, dann werden einfafch EINMAL die Kreise neu gezeichnet, sonst passiert da nix, egal was man während dem zeichnen für Gesten macht.

Probiert mit Aldi Lifetab Android 3.2 (nicht gerootet)
 

Skywalker

Member
Licensed User
Longtime User
Also das kann eigentlich nicht sein.
Ich habe mir nun auch den Emulator für Android 3.2 installiert und auch dort werden die Gesten gepuffert.
Wenn ich nach dem Aufbau des ersten Bildes z.B. 3x nach rechts wische, werden die Kreis auch 3x hintereinander neu dargestellt.
Nur wenn man auf "Reset" drückt, passiert das nicht.
 
Top