XbpBrowse refreshen [Erledigt]

Grafische Primitive, XbaseParts und Darstellungsfragen allgemein.

Moderator: Moderatoren

Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

XbpBrowse refreshen [Erledigt]

Beitrag von Jan »

Hallo,

ich arbeite gerade an einem XbpBrowse, der regelmäßig refresht werden soll. Damit die angezeigten Daten aus einer im Hintergrund fortlaufend aktualisierten dbf immer aktuell auf dem Bildschirm erscheinen. Ich habe da mal zwei Varianten versucht.

1) Den Refresh in die Event-Schleife gelegt, verbunden mit einer Verzögerung von 0,1 Sekunden. Mir war dabei etwas unwohl, weil ich die Eventschleife dafür nicht mißbrauchen wollte. Leider funktionierte das auch nur, wenn man mit der Maus über den Browse fuhr. Dann wurde wirklich refreshed. Also wohl nicht so der ganz gute Weg.

2) Mal ganz brachial diese Zeile eingefügt:

Code: Alles auswählen

oBrowse:stableBlock := {|| SetAppFocus(oBrowse), Inkey(1), oBrowse:refreshAll()}  
Das funktioniert wirklich. Flackert zwar bei jedem Refresh, aber man kann ja nicht alles haben ... :( Aber der große Nachteil ist: Nach wenigen Minuten stürzt das gesamte Programm kommentarlos ab. Als ob da irgendwas überlaufen würde.

Wie macht Ihr das? Was wäre der eleganteste Weg, sowas zu erledigen?

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: XbpBrowse refreshen

Beitrag von brandelh »

Die normale Eventloop wartet ja bis ein Ereignis eintritt, also wird auch nichts refreshed, wenn nichts passiert (Maus, Keyboard etc.)
Die eleganteste Lösung dürfte ein eigenen Thread sein, regelmäßig die Daten anzeigt, aber 0,1 Sekunden also 10x je Sekunde ist viel zu oft :!:
Wenn du die Funktion SetTimerEvent() nicht schon benutzt, könntest du das einrichtigen.

Im dortigen Beispiel wird alle Sekunde die Uhrzeit angezeigt:

SetTimerEvent(100, {|| DispOutAt(0, 0, Time()) } )

Ich würde eine Methode des Fensters machen, die sich um die Daten (DBF Refreshall) und die Anzeige kümmert und diese im Event aufrufen:

SetTimerEvent(100, {|| ::RefreshBrowser() } )

ich habe es jetzt nicht getestet, aber das sollte so gehen, wenn nicht, einfach einen eigenen Thread eröffnen ...
Gruß
Hubert
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: XbpBrowse refreshen

Beitrag von brandelh »

PS: inkey(1) in einer GUI Anwendung ?
Gruß
Hubert
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: XbpBrowse refreshen

Beitrag von Jan »

brandelh hat geschrieben:PS: inkey(1) in einer GUI Anwendung ?
:D Naja, es geht halt. Auch wenn das ansich irgendwie nicht zusammen passen sollte.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: XbpBrowse refreshen

Beitrag von Jan »

Hallo Hubert,

hmm, SetTimerEvent() ist sicher mal wert angesehen zu werden. Hab ich glaube ich bislang nicht benutzt.

Aber ob daß das Richtige ist? Ich will ja nicht alle paar Sekunden den Browse neu aufbauen. Das wäre dann wohl doch zu viel Overhead. Ich will den einfach nur aktualisieren.

Oder versteh ich Dich da miß?

Und klar, Inkey(.1) war auch falsch. Ich hab den wirklich auf 1 stehen. Solange ich da noch rum teste. Später im scharfen Betrieb soll die Verzögerung dann bei 5 oder sogar 10 Sekunden liegen.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: XbpBrowse refreshen

Beitrag von brandelh »

Hallo Jan,

Ich denke, du möchtest jede Sekunde die Daten neu anfordern und dann die Anzeige refreshen und NICHT das XbpBrose() Objekt neu erzeugen ...
Wenn das richtig ist, dann ist SetTimerEvent() ein guter Weg, wobei man könnte dort auch einen PostAppEvent hinterlegen ... aber egal wie, was muss man tun ?

Code: Alles auswählen

[b]oB:refreshAll()[/b]  ... definiert die Anzeige aller Datenzeilen im Browse-Fenster als ungültig.
[b]oB:forceStable()[/b] ...  Im nächsten Stabilisierungszyklus werden daher die Daten aus der Datenquelle via oXbpColumn:dataLink neu eingelesen und angezeigt. 
Ich würde das maximal alle 5 Sekunden durchführen, je nach Anwender im Netzwerk kann das häufig Refreshen schon ein Problem werden.
In meinen Anwendungen habe ich immer nur nach eigenen Änderungen Refreshed, oder wenn der Anwender das angefordert hat.

PS: ohne oB:refreshAll() macht oB:forceStable() nach meiner Meinung keinen Sinn, wenn die Änderungen nicht auf dem eigenen Rechner erfolgt sind.
Gruß
Hubert
Benutzeravatar
Koverhage
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2470
Registriert: Fr, 23. Dez 2005 8:00
Wohnort: Aalen
Hat sich bedankt: 102 Mal
Danksagung erhalten: 3 Mal
Kontaktdaten:

Re: XbpBrowse refreshen

Beitrag von Koverhage »

Ich würde einen Schalter setzen, z.B. lMustRefresh
Wenn der auf Ja steht, refreshall
Dieser Schalter muss bei Änderungen in der db gesetzt werden, und nach dem refresh auf .f.
Gruß
Klaus
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: XbpBrowse refreshen

Beitrag von brandelh »

Wenn man SELBST die Änderungen macht, reicht auch RefreshCurrent(), wenn aber andere die DBF / SQL Server ändern, dann nützt nichts außer die Daten neu einzulesen.
Gruß
Hubert
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9358
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: XbpBrowse refreshen

Beitrag von Tom »

Originelle Ansätze.

Ich würde das viel simpler lösen. Beim Aufruf der Tabelle wird ein Timestamp mit den Dateidaten generiert, beispielsweise DtoS(FileDate())+FileTime() (Funktionen aus den Tools, aber es gibt auch andere, verlässlichere). In der Eventloop wird alle x Sekunden geprüft, ob die aktuellen Daten neuer sind, dann wird der Timestamp aktualisiert und ein RefreshAll() ausgelöst. Feddisch. Hat den Vorteil, dass es kein unmotiviertes Flackern gibt, obwohl sich nix getan hat, und selbst in ungepatchten SMB2-Netzen beträgt die Latenz höchstens 10+x Sekunden.

Alternativ kann man mit jeder Änderung/Ergänzung auch Nachrichtendateien anlegen oder aktualisieren.
Herzlich,
Tom
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: XbpBrowse refreshen

Beitrag von Jan »

Hallo Hubert, Klaus, und Tom,

da kommen ja wirklich gute Ideen zusammen!

Ich könnte mir vorstellen das mir der Weg von Tom am Besten gefallen würde. Ich werde das mal durchtesten.

Wobei allerdings die Frage offen bleibt, warum das ganze Programm nach einigen Minuten sich einfach verabschiedet. Was es nicht macht wenn ich den Refresh weg lasse.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9358
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: XbpBrowse refreshen

Beitrag von Tom »

Wobei allerdings die Frage offen bleibt, warum das ganze Programm nach einigen Minuten sich einfach verabschiedet.
Du meinst, mit Deiner oBrowse:stableBlock-Lösung? Nunwohl. Der Slot wird ausgewertet, wenn das Browse stabilisiert wurde. Da im Block ein RefreshAll() ausgelöst wird, was in aller Regel wiederum eine Stabilisierung nach sich zieht, wirst Du ganz simpel in einem Stack Overflow landen - und/oder in einer Endlosrekursion. Das ist, wie Du selbst erklärst, tatsächlich recht brachial, und es wundert mich, dass es überhaupt für ein paar Minuten funktioniert. :wink:
Herzlich,
Tom
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: XbpBrowse refreshen

Beitrag von Jan »

Tom,

leider hat Deine Lösung ein kleines Problem: Ein Event wird nur ausgelöst, wenn da auch was passiert. Wenn der Browse aber einfach nur still und leise auf dem Monitor steht, niemand da eine Maus drüber schubst oder ähnliches macht, dann läuft der nicht in die Event-Schleife rein.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2121
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 30 Mal
Danksagung erhalten: 72 Mal

Re: XbpBrowse refreshen

Beitrag von Werner_Bayern »

Event-Schleife <nTimeOut> ändern!
es grüßt

Werner

<when the music is over, turn off the lights!>
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9358
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: XbpBrowse refreshen

Beitrag von Tom »

Oder in der Eventschleife machen, aber außerhalb der Eventauswertung.
Herzlich,
Tom
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: XbpBrowse refreshen

Beitrag von Jan »

Hallo Tom,

so hab ich das im Moment eingebaut:

Code: Alles auswählen

DO WHILE .T.
   nEvent := AppEvent(@mp1, @mp2, @oXbp)
   oXbp:handleEvent(nEvent, mp1, mp2)

   aDirectory := Directory(pfadExe() + pfadDaten() + "knx.dbf")
   IF .NOT. aDirectory[1][F_WRITE_TIME]== cAktuelleZeit
      oBrowse:refreshAll()
      cAktuelleZeit := aDirectory[1][F_WRITE_TIME]
   ENDIF

ENDDO
Was soll ich daran ändern???

Ich hatte übrigens eben noch ein Problem: Der hat so oder so nicht refreshed. Weil die Datei-Zeit immer gleich geblieben ist. Egal was ich da rein geschrieben habe, die änderte sich nicht. Erst nachdem ich ein DbCommit() eingebaut habe, habe ich unter Windows wirklich das letzte Schreibdatum drin. Böse Falle!

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9358
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: XbpBrowse refreshen

Beitrag von Tom »

Hallo, Jan.

Ein DbSkip(0) nach dem Schreiben oder Löschen hat ähnliche Effekte.

Ich würde um das ständige Auslesen der Dateidaten herum noch einen Timer setzen; in Deiner vorliegenden Konstruktion wird es andauernd ausgelöst. Du kannst auch mit SetTimerEvent() in eine Funktion verzweigen, die das übernimmt. Und Du musst wahrscheinlich früher oder später darauf achten, dass ein Refresh des Browses natürlich nicht ausgelöst werden darf, wenn im aktuellen Dialog gerade etwas damit geschieht, z.B. eine Bearbeitung stattfindet. Vorausgesetzt, es gibt eine solche Funktionalität.
Herzlich,
Tom
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: XbpBrowse refreshen

Beitrag von brandelh »

Deine Schleife arbeitet wieder nur nach Events, du wolltest das aber anders ;-)

Code: Alles auswählen

nNextRefresh := 0
cFile := pfadExe() + pfadDaten() + "knx.dbf" // bleibt gleich, also auslagern
DO WHILE .T.
   nEvent := AppEvent(@mp1, @mp2, @oXbp, 100 )  // spätestens 1 Sekunde beenden
   if nEvent # xbe_None
      oXbp:handleEvent(nEvent, mp1, mp2)
   endif // *** das hier war vorher ganz unten.
   if nNextRefresh < seconds()
      nNextRefresh := seconds() + 5 // alle 5 Sekunden
      aDirectory := Directory(cFile)
      // wenn das mal gut geht, bei den aktuellen Metadaten ... und bei SQL ?
      IF .NOT. aDirectory[1][F_WRITE_TIME]== cAktuelleZeit
         oBrowse:refreshAll()
         cAktuelleZeit := aDirectory[1][F_WRITE_TIME]
      ENDIF
   endif 
ENDDO
Anmerkung, hier wird ohne Event auch nicht refreshed, TOM hat es unten verbessert ...
PS: besser ich verbessere es gleich selbst auch hier !
Gruß
Hubert
Benutzeravatar
Werner_Bayern
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2121
Registriert: Sa, 30. Jan 2010 22:58
Wohnort: Niederbayern
Hat sich bedankt: 30 Mal
Danksagung erhalten: 72 Mal

Re: XbpBrowse refreshen

Beitrag von Werner_Bayern »

nEvent := AppEvent(@mp1, @mp2, @oXbp)
Wartet solange, bis ein Ereignis eintritt. Verwendest Du den 4. Parameter <nTimeOut>, hast Du nicht das von Dir beschriebene Problem, dass die Maus bewegt werden muss.
es grüßt

Werner

<when the music is over, turn off the lights!>
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9358
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: XbpBrowse refreshen

Beitrag von Tom »

Hallo, Hubert.
Deine Schleife arbeitet wieder nur nach Events, du wolltest das aber anders
In Deinem Code aber erst recht. :wink: Edit: Quatsch. Ich hatte den Parameter bei AppEvent übersehen. Schulljung.

Außerdem stimmt das nicht. Jan hatte das gleich am Anfang hinter das "DO WHILE .T." gesetzt, wodurch es ganz unabhängig von eingehenden Events eigentlich pausenlos ausgeführt werden müsste.
Zuletzt geändert von Tom am Di, 09. Dez 2014 12:42, insgesamt 1-mal geändert.
Herzlich,
Tom
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9358
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: XbpBrowse refreshen

Beitrag von Tom »

Wartet solange, bis ein Ereignis eintritt.
Stimmt. Also entweder den Timeout-Parameter verwenden oder mit SetTimerEvent auslagern.
Herzlich,
Tom
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9358
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 101 Mal
Danksagung erhalten: 361 Mal
Kontaktdaten:

Re: XbpBrowse refreshen

Beitrag von Tom »

Huberts Vorschlag müsste mit einer kleinen Änderung eigentlich gut funktionieren:

Code: Alles auswählen

nNextRefresh := 0
cFile := pfadExe() + pfadDaten() + "knx.dbf" // bleibt gleich, also auslagern
DO WHILE .T.
   nEvent := AppEvent(@mp1, @mp2, @oXbp, 100 )  // spätestens 1 Sekunde beenden
   if nEvent # xbe_None
      oXbp:handleEvent(nEvent, mp1, mp2)
   endif // weil das Refresh sonst bei keinem Event - xbe_None - nie ausgelöst würde
   if nNextRefresh < seconds()
       nNextRefresh := seconds() + 5 // alle 5 Sekunden
       aDirectory := Directory(cFile)
       // wenn das mal gut geht, bei den aktuellen Metadaten ... und bei SQL ?
       IF .NOT. aDirectory[1][F_WRITE_TIME]== cAktuelleZeit
          oBrowse:refreshAll()
          cAktuelleZeit := aDirectory[1][F_WRITE_TIME]
       ENDIF
   endif
ENDDO
Herzlich,
Tom
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: XbpBrowse refreshen

Beitrag von brandelh »

@ TOM

hast Recht, da habe ich mich bei den IF / ENDIF vertan ... das kommt davon wenn man es nicht probiert :D
Gruß
Hubert
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14651
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 88 Mal
Kontaktdaten:

Re: XbpBrowse refreshen

Beitrag von Jan »

Hallo Jungs,

hervorragende Arbeit! Vielen Dank für die Hilfe :thumbright: So funktioniert das einwandfrei.

Jan
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12906
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 45 Mal

Re: XbpBrowse refreshen [Erledigt]

Beitrag von AUGE_OHR »

Code: Alles auswählen

oBrowse:stableBlock := {|| SetAppFocus(oBrowse), Inkey(1), oBrowse:refreshAll()}
in einen o:StableBlock sollte man KEINE weitere "Navigation" Befehle oder self:Methoden ausführen da diese rekursive wieder zum o:StableBlock führen

Code: Alles auswählen

xbe_None
IST ein Event der NUR durch den 4th Parameter von AppEvent ausgelöst wird.
gruss by OHR
Jimmy
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15695
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: XbpBrowse refreshen [Erledigt]

Beitrag von brandelh »

AUGE_OHR hat geschrieben:

Code: Alles auswählen

xbe_None
IST ein Event der NUR durch den 4th Parameter von AppEvent ausgelöst wird.
das stimmt nicht.

xbe_None ist der Wert, der von AppEvent zurückgegeben wird, wenn KEIN EVENT sondern ein TIMEOUT (4. Parameter) die Funktion beendet hat :!:
Gruß
Hubert
Antworten