Eieruhr

Alle Fragen um die Programmierung, die sich sonst nicht kategorisieren lassen. Von Makro bis Codeblock, von IF bis ENDIF

Moderator: Moderatoren

Antworten
peternmb
1000 working lines a day
1000 working lines a day
Beiträge: 525
Registriert: Mi, 01. Feb 2006 16:22
Wohnort: 06618 Naumburg

Eieruhr

Beitrag von peternmb »

Hallo,

ich möchte in einem seperaten Thread einen Timer laufen lassen, der Sekunden rückwärts auf 0 zählt.
Was muss ich denn da bei event festlegen?
Egal wie ich`s mache: entweder reagiert der Zähler auch auf Mausbewegungen oder ich kann das Fenster nicht bewegen/schleßen.

Code: Alles auswählen

...
oMenu:AddItem({"Timer", {|| ExtraThread("timer") } })  
...


#include "Gra.ch"
#include "Xbp.ch"
#include "Appevent.ch"

proc timer
//
LOCAL nEvent:=xbe_None, ;
      min:=3,sec:=0, ;
      BGfarbe:=GRA_CLR_WHITE, ;
      T1farbe:=GRA_CLR_RED, ;
      T2farbe:=GRA_CLR_BLUE
//
oDlgTi:= XbpDialog():new( AppDesktop(),SetAppWindow(), {0,0},{300*F,225*F})
oDlgTi:maxButton:= .F.
oDlgTi:title    := "Timer"
oDlgTi:icon := 100
oDlgTi:Close    := { || oDlgTi:destroy() }
oDlgTi:create()
oDlgTi:drawingArea:SetColorBG( BGfarbe )
center(oDlgTi)
//
StaTi1:= XbpStatic():new(oDlgTi,,{0,145*F},{300*F,45*F}, ;
                        {{XBP_PP_BGCLR,BGfarbe},{XBP_PP_FGCLR,T1farbe} } )               
StaTi1:type   := XBPSTATIC_TYPE_TEXT
StaTi1:setFontCompoundName( str(36*F/dpi,2,0)+".Arial" )
StaTi1:caption:="Restzeit:"
StaTi1:options := XBPSTATIC_TEXT_CENTER 
StaTi1:create()
//
StaTi2:= XbpStatic():new(oDlgTi,,{0,0*F},{300*F,140*F}, ;
                        {{XBP_PP_BGCLR,BGfarbe},{XBP_PP_FGCLR,T2farbe} } )  
StaTi2:type   := XBPSTATIC_TYPE_TEXT
StaTi2:setFontCompoundName( str(96*F/dpi,3,0)+".Arial" )
StaTi2:caption:=str(min,1,0)+":"+strzero(sec,2,0)
StaTi2:options := XBPSTATIC_TEXT_CENTER 
StaTi2:create()
//
DO WHILE nEvent <> xbeP_Close   
   nEvent := AppEvent( @mp1, @mp2, @oXbp, 100 )
   //
   if nEvent # xbe_None
      oXbp:HandleEvent( nEvent, mp1, mp2 )
   else
      sec=sec-1
      if sec < 0
         sec=59
         min=min-1   
      endif
      //   
      if min < 0
         msgbox("Die Zeit ist abgelaufen!")
         exit
      else
         StaTi2:setCaption(str(min,1,0)+":"+strzero(sec,2,0))
      endif 
   endif
   //
ENDDO
//
oDlgTi:destroy()
//
return


#include "Thread.ch"
FUNCTION ExtraThread(ExPrg)
//
LOCAL oThread
oThread:=Thread():new()
oThread:setPriority( PRIORITY_NORMAL )  //HIGHEST )
oThread:start(ExPrg)
//
RETURN nil

BIK
UDF-Programmierer
UDF-Programmierer
Beiträge: 68
Registriert: Di, 23. Aug 2011 14:34
Hat sich bedankt: 1 Mal

Re: Eieruhr

Beitrag von BIK »

nachstehend ein kleines Beispiel, wie du an die Sache herangehen kannst:

Code: Alles auswählen

   oBtn := xbpPushbutton ...
   
   oThread := Msg_Thread(  ):new() 
   oThread:setPriority (PRIORITY_IDLE)
   oThread:Start( ,  nTimeout , oBtn )
 
   DO WHILE nEvent <> xbeP_Close  
   
      nEvent := AppEvent( @mp1, @mp2, @oXbp, 100 )
      oXbp:handleEvent(nEvent,mp1,mp2)

   ENDDO

   * -------------------- *
   * destroy timer object *
   * -------------------- *
   IF .NOT. oThread == nil
     oThread:terminate() 
   ENDIF






CLASS Msg_Thread FROM Thread 
      PROTECTED: 
         VAR terminated 
      EXPORTED: 
         VAR Max_Seconds 
 
         INLINE METHOD init ( )
            ::Thread:init() 
            ::terminated  := .F. 
         RETURN self 
 
         INLINE METHOD terminate 

         RETURN ( ::terminated := .T. ) 
 
         METHOD execute, checkTermination 
   ENDCLASS       
 
   METHOD Msg_Thread:execute ( Max_Seconds ,  oBtn  )
     
     LOCAL nSeconds := Max_Seconds/100
     LOCAL nStart := Seconds() 
     LOCAL nEnd := nStart+nSeconds
     
     if nEnd > 86399  // after midnight
       nEnd := nStart - 86399 + nSeconds 
     endif
     
   
     DO WHILE Seconds() < nEnd
        oBtn:SetCaption( "noch "+ALLTRIM(str( nSeconds -- ,3 ))+" sec."  )
         
        sleep(50) 
         
        ::checkTermination() 
      ENDDO 
      
      EVAL( oBtn:activate ,,,  oBtn )
      
   RETURN self 
 
   METHOD Msg_Thread:checkTermination 
      IF ::terminated 
         ::terminated := .F. 
         ::quit() 
      ENDIF 
   RETURN self 
Benutzeravatar
AUGE_OHR
Marvin
Marvin
Beiträge: 12903
Registriert: Do, 16. Mär 2006 7:55
Wohnort: Hamburg
Hat sich bedankt: 19 Mal
Danksagung erhalten: 44 Mal

Re: Eieruhr

Beitrag von AUGE_OHR »

peternmb hat geschrieben:Was muss ich denn da bei event festlegen?
Egal wie ich`s mache: entweder reagiert der Zähler auch auf Mausbewegungen oder ich kann das Fenster nicht bewegen/schleßen.
der 4th Parameter von Appevent() reagiert zwar auf ein "Timeout" aber auch auf jeden anderen Event.
der Einsatz eines Thread ist hier der bessere Ersatz, nur ein o:SetInterval(nTime) fehlt dir hier.

mit o:SetInterval(nTime) wird nach vorgegebener Zeit der o:Start( Codeblock ) ausgeführt.
um ihn "immer wieder" auszuführen darf da keine DO / WHILE sein denn so lange der Code im Thread aktive ist kann er nicht gleichzeitig "noch mal" ausgeführt werden.

einen Thread "von aussen stoppen" tust du mit o:SetInterval(NIL)

---

der Code von BIK wurde nun als Class ausgeführt welche dir die Möglichkeit gibt "innerhalb" des Thread mit VAR "terminated" für ein Ende zu sorgen.
da bei dir Anfang / Ende feststeht wäre eine Class wohl die bessere Lösung
gruss by OHR
Jimmy
Antworten