locked
MouseWheel im Grid - Sys(2060) RRS feed

  • Frage

  • Hallo zusammen,

    ich habe eine Maske, in der auf der linken Hälfte ein Grid dargestellt wird und einen Ausschnitt aus einer Tabelle anzeigt.  Auf der rechte Seite werden zu jeder Zeile im Grid bestimmte Informationen graphisch dargestellt. Die Metadaten zu den Graphikelementen befinden sich ebenfalls in der Tabelle, die dem Grid unterliegt. Ich kann mich durch das Grid bewegenund auch im Grid scrollen und die Graphikseite wird ebenfalls entsprechend gescrollt. Das Scrollen habe ich mittels des Mousewheel-Events realisiert und habe darin auch die entsprechenden Zeilen integriert, die mir die Informationen über die erste und die aktuelle Zeile im Grid liefern.

    Bis dahin ist alles gut.

    Das Problem ist nun, wenn ich am Mausrad etwas heftiger drehe, läuft offensichtlich der Mouswheel-Event über, und er benötigt eine gewisse Zeit, bis er wieder zur Ruhe kommt. Das sieht man auch, wenn ich mir den Event-Tracker im Debugger ansehe. Der MW-Event feuert noch ne Zeit lang nach (mit abnehmenden Parametern). Während diesem Nachfeuern scrollt das Grid nicht, der Mauszeiger auf dem Bildschirm ist wie wild am Blinken und das Programm reagiert nicht mehr. Das dauert dann etwa 1-2 Sekunden, und dann ist wieder alles ok. Ich vermute mal, daß der MW-Event schneller feuert, als meine Routine abgearbeitet wird.

    Es gibt die Funktion Sys(2060), welches das Verhalten des MW-Events beeinflussen soll. Ich habe versucht, im Init der Form mit den unterschiedlichen Parametern auf das Verhalten Einfluß zu nehmen, aber es zeigt sich keine Veränderung.

    Könnte mir jemand nen Tip geben, an welcher Stelle ich möglicherweise eingreifen kann.

    Gruß

    Christoph

    Mittwoch, 29. November 2017 15:13

Alle Antworten

  • Wie hast Du denn jetzt SYS(2060) genutzt?

    Und was macht das Mousewheel Event? Wie lange braucht es?

    Tschüß, Olaf.


    Olaf Doschke - http://www.doschke.name

    Mittwoch, 29. November 2017 16:31
  • Hallo Christoph,

    grundsätzlich sollte man in einen Event nur Code einklinken, der relativ schnell abgearbeitet wird.

    Das Problem kenne ich und schlage Dir deshalb folgende Lösung vor:

    1) setze auf die Form einen Timer Timer1 mit:

    THISFORM.Timer1.Enabled = .F.
    THISFORM.Timer1.Interval = 10


    2) im MouseWheel-Event rufst Du jetzt nicht mehr Deine Routine auf, sondern nur noch:

    THISFORM.Timer1.Enabled = .T.
    THISFORM.Timer1.Reset


    3) im Timer-Event:

    WITH THIS
        IF .Enabled
            .Enabled = .F.
    
            hier jetzt Deine Routine aufrufen
        ENDIF
    ENDWITH

    So wird nun dafür gesorgt, daß Dein MouseWheel-Event nicht mehr "überläuft" :-)

    Gruß, Stefan

    Mittwoch, 29. November 2017 22:07
  • Hallo Stefan, hallo Olaf.

    Erstmal vielen Dank für eure Hinweise.

    ich habe Sys(2060,1) im Init der Form gesetzt.

    Da ich wissen muß, wie die Daten im Grid aussehen (z. B. welche Daten stehen in der ersten Zeile des Grids) und ich im MW-Event hablwegs sicher und verläßlich mit RelativeRow umgehen kann, steht da schon ein bischen Code drin. Ebenso rufe ich aus dem MW-Event die Erzeugung der Grafik auf.

    Erzeugung Graphik heißt: 90 x Addobject und jedes Object hat ca. 20 Eigenschaften.Eigenschaften werden zum Teil aus den Daten in der Tabelle, die auch dem Grid als Quelle dient, berechnet

    Ich weiß schon, daß das nicht die beste Art und Weise ist (mea culpa); die MW-Methode benötigt schon Zeit. Aber die Restriktionen im Grid haben mich auf diese Möglichkeit gebracht.

    Vor diesem Hintergrund hatte ich die Idee, die Empfindlichkeit des MW-Events etwas zu zügeln.

    Ich befürchte auch, daß die Ausführung des Codes in einem Timer-Event kein gesicherter Zugriff auf die Satzreihenfolge im Grid gegeben ist. Müßte ich ausprobieren.

    Gruß

    Christoph

    Donnerstag, 30. November 2017 07:19
  • 1. An Stefan: Der Check IF .ENABLED ist recht sinnlos, nur ein Timer, der enabled ist kann feuern. Ich würde dann noch eine weitere Eigenschaft anlegen, die dem MWEvent anzeigt, dass der Timer gerade läuft und ein weiteren Timer Event auszulösen noch zu früh wäre. Das würde man dann zum Schluss wieder resetten, enabled aber auf .F. stehen lassen.

    2. Christoph, Du willst Mousewheelevents zusammenfassen, also SYS(2060,0), das ist aber sowieso default. mit SYS(2060,1) verschlechtert sich die Situation nur.

    Man könnte im Gesamtzusammenhang auf das MW-Event als Auslöser verzichten und einfach alle 250ms oder was auch immer passend ist eine Grafik aktualisieren.

    Und warum sollte ein Timer nicht Zugriff auf das Grid haben? 

    a) ein Timer ist kein Control, dass den Focus bekommt, es ändert ihn also auch entsprechend nicht. Das lässt auch Eigenschaften unverfälscht, die davon abhängen, dass das Grid den Fokus hat.

    b) ein Timer, den Du auf das Form legst hat anders als ein lediglich in eine Variable instanzietes Timerobjekt auch den Kontext THISFORM samt aller Unterobjekte oder THIS.Parent, z.B. ein Timer auf selber Ebene des Grids (also neben dem Grid auf demselben Container, Pageframe, form selbst, in was auch immer das Grid liegt bedeutet THIS.PARENT.GridXYZ Zugriff auf das Grid.

    Im Zweifelsfall kann das MW-Event immer noch genutzt werden, um in Benutzerdefinierten Timer oder Formulareigenschaften Informationen abzulegen, die der Timercode benötigt.

    Tschüß, Olaf.


    Olaf Doschke - http://www.doschke.name

    • Bearbeitet Olaf Doschke Donnerstag, 30. November 2017 11:22
    Donnerstag, 30. November 2017 11:17
  • Mit Euren Tipps habe ich die Sache wieder auseinander genommen.

    Die Sys(2060)-Sache habe ich dann wohl falsch interpretiert. Hatte auf ne Verbesserung gehofft... Sys ist draußen.

    Zum einen: Ich habe das MW Event wesentlich verschlankt (es verschluckt sich offenbar nicht mehr). Den Graphikaufbau mache ich nur noch initial (Start der Form) und wenn sich die erste Zeile des Grids inhaltlich ändert (nach einem Scroll). Ansonsten versuche ich mit den Events AfterRowColChange und Scrolled auszukommen. Mal sehen ob mir das gelingt.

    Danke euch jedenfalls.

    Christoph

    P.S.

    Wenn nicht melde ich mich nochmals...

    Donnerstag, 30. November 2017 12:14
  • Hallo Olaf,

    Deinem Hinweis 1. zum Check IF .Enabled stimme ich theoretisch sofort zu!

    Jedoch hat bei mir die Praxis gezeigt, daß es nötig ist!

    - meine Vermutung: ein .Enabled = .F. fruchtet nicht sofort ...

    Gruß, Stefan

    Donnerstag, 30. November 2017 17:07
  • Bei dem kurzen Interval von 10ms mag angehen, dass Enabled nicht schon .F. ist, aber dann würden sich zwe Timer Events überholen und das geht meines Wissens nach sowieso nicht, Timer Events werden gequeued ausgeführt.

    Selbst wenn doch nicht, dann ändert das auch nichts an der Doppelausführung, das .Enabled=.F. kommt nur noch später zum Tragen.

    Was richtig ist sind Intervals unter ca 50ms machen Probleme. Christof Wollenhaupt hat dazu mal was geschrieben und die Idee eines Run Once Timers umgesetzt, der sich selbst releast. D.h. so ein Timer erstellt man als Wegwerfobjekt, um sein Timer Event nur einmalig auszuführen. Das geht dann durchaus ineinander greifend mit mehreren Timerobjekten, eben durch mehrere voneinander unabhängige Timerobjekte.

    Ich krieg jetzt keinen Überlapp hin, wenn ich es auch noch so sehr erzwinge:

    _screen.AddObject("timer1","mytimer")
    
    CREATE CURSOR crsTimes (icounter int, bseconds B)
    DEFINE CLASS mytimer as timer
      interval=1
      enabled=.t.
      counter=0
      
      PROCEDURE timer()
         this.counter = this.counter + 1 
         INSERT INTO crsTimes VALUES (this.counter, SECONDS())
         DOEVENTS FORCE
         INSERT INTO crsTimes VALUES (this.counter, SECONDS())
         DOEVENTS FORCE
         INSERT INTO crsTimes VALUES (this.counter, SECONDS())
         DOEVENTS FORCE
         INSERT INTO crsTimes VALUES (this.counter, SECONDS())
         DOEVENTS FORCE
      ENDPROC 
    ENDDEFINE

    Die DOEVENTS geben einer Selbstüberholung jede Chance, die man sich nur geben kann, aber jeweils vier aufeinanderfolgende Datensätze haben im Anschluss den gleichen counterstand und Seconds() ist stetig steigend, typischerweise sogar 50-60ms pro Timer Event, so daß man 50-60 ineinandergreifende gleichzeitg ablaufende Events erwarten könnte, was zwar immer noch stetig steigende SECONDS() Werte haben sollte, aber vor und zurück springende Counterstände in den Datensätzen verursachen würde.

    Tschüß, Olaf.


    Olaf Doschke - http://www.doschke.name

    Donnerstag, 30. November 2017 22:36
  • Hallo zusammen.

    Ich muß doch noch etwas fragen:

    Ich habe das Grid-Handlich soweit auf der Reihe; Cursor-Tasten, Mausrad, PGUP,PGDN sowie anklicken einer Teilgrafik (ausßerhalb des Grids) und entsprechende Positionierung / Auslesen des ersten und des aktuellen Datensatzes funktionieren. Habe zwar das MW-Event ziemlich verschlankt, aber dennoch kommt es zum Überlaufen des MW-Events (muß man eben dann langsam mit am Maus-Rad drehen).

    Aber ein anderer Punkt stört mich dennoch.

    Kann ich bei einer vertikalen Scrollbar am Grid das Klicken auf die Richtungspfeile bzw. das Verschieben des Scrollbalkens abfangen? Ich habe auch das Phänomen, dass der Parameter in der Scrolled-Methode nur die Werte 0 oder 1 annimmt (größere Parametewerte für das Verschieben mit Scrollbar werden nicht übergeben).

    Gruß

    Christoph

    Montag, 4. Dezember 2017 12:01
  • Hi Christoph,

    im .scrolled Event sind die Werte 2 und 3  nur dann vorhanden, wenn der Bereich zwischen Pfeil und Balken geklickt wird.

    Evtl. kannst Du ja die vertikale Scrollbar ganz abschalten und platzierst am rechten Rand des Grids einfach 4 Buttons für PGUP,UP1,DN1,PGDN und löst beim click einfach einen DoScroll mit der jeiligen Richtung (0,1,2,3) aus.

    HTH


    Gruss / Best regards
    -Tom
    Debugging is twice as hard as writing the code in the first place.
    Therefore, if you write the code as cleverly as possible,
    you are, by definition, not smart enough to debug it. 010101100100011001010000011110000101001001101111011000110110101101110011


    • Bearbeitet Tom Borgmann Montag, 4. Dezember 2017 14:49 Kürzel geändert
    Montag, 4. Dezember 2017 14:04
  • Hallo Christoph,

    beim mir verhält es sich mit dem den Parametern vom Scrolled-Ereignis folgendermaßen:

    - klicken auf kleinen Pfeil nach oben: 0
    - klicken auf kleinen Pfeil nach unten: 1

    - klicken auf Bereich oberhalb Scrollbar: 2
    - klicken auf Bereich unterhalb ScrollBar: 3

    - Scrollbar nach oben verschieben: 0
    - Scrollbar nach unten verschieben: 1

    - mit Mausrad nach oben scrollen: 2
    - mit Mausrad nach unten scrollen: 0    (hier hätte ich eher 3 erwartet)

    bei Tastatur-Bedienung wird kein Scrolled-Ereignis ausgelöst!

    Gruß, Stefan


    Montag, 4. Dezember 2017 15:00
  • Hallo Tom,

    ja zusätzliche Buttons waren auch schon meine Idee. (Ich hatte eigentlich gehofft, ich würde mich ungeschickt anstellen und ein netter Kollege gibt mir hier den oder die entscheidenen Tipps)

    Trotzdem vielen Dank

    Gruß

    Christoph

    Dienstag, 5. Dezember 2017 08:52
  • Hallo Stefan,

    d. h. ich müßte über die bekannten Events gehen, mit all den Spezialitäten. Werde wohl, wie von Tom ebenfalls empfohlen, separate Button hinlegen, die dann die entsprechende großräumige Bewegung innerhalb des Grids machen.

    Gruß und vielen Dank.

    Christoph

    Dienstag, 5. Dezember 2017 08:55
  • Insgesamt wäre vielleicht doch einfacher, in einem Timer auf die aktuelle Position zu reagieren. Es war mir schon klar, dass Dir Scrolled Ereignisse nicht die Scrollweite angeben, dazu greifst Du ja RelativeRow ab.

    Tschüß, Olaf.


    Olaf Doschke - http://www.doschke.name


    • Bearbeitet Olaf Doschke Donnerstag, 7. Dezember 2017 10:27
    Mittwoch, 6. Dezember 2017 06:29
  • Hallo zusammen,

    hab jetzt ales so, wie es Sinn macht. Ohne SCrollbar aber mit 4 Extra-Buttons. Die bewegen mich durchs Grid und ich weiß immer, welcher Satz in der obersten Zeile steht, damit ich die Graphik entsprechend aktualisieren kann.

    Vielen Dank für Eure Unterstützung

    Gruß

    Christoph

    Mittwoch, 6. Dezember 2017 15:43