Progressbar [erledigt]

Klassen, Objekte, Methoden, Instanzen

Moderator: Moderatoren

Antworten
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:

Progressbar [erledigt]

Beitrag von Koverhage »

Hallo,

habe heute mal ein anderes Problem.
Kenne mich mit Klassen und Methoden noch nicht so aus. Habe in den Xbase++ News eine Progressbar gefunden die mir sehr gut gefällt.
In der Original Version wurde die Prozentanzeige zentriert dargestellt. Habe das geändert das diese immer links
erscheint. Möchte das jetzt aber wahlweise haben, wenn ich einen Text übergebe (cTitle) sollte das von links
in etwa so sein
10% von Muster.pdf erstellt.
wenn ich keinen Text übergebe sollte die Prozentzahl zentriert dargestellt werden.
Wo ich das machen muss ist mir klar, Zeile 69 bzw. 70, aber wie übergebe ich den Parameter ?
habe mir das so gedacht:

if empty(cTitle)
::Percentage:Options := XBPSTATIC_TEXT_CENTER+XBPSTATIC_TEXT_VCENTER
else
::Percentage:Options := XBPSTATIC_TEXT_LEFT+XBPSTATIC_TEXT_VCENTER
endif

und in Zeile 333
IF !EMPTY(::Percent)
if empty(cTitle)
::Percent:SetCaption(STR(INT(100*::_current/(::maximum-::minimum)),3)+"%")
else
::Percent:SetCaption(STR(INT(100*::_current/(::maximum-::minimum)),3)+"%"+" von "+cTitle+ " erstellt)
endif
ENDIF


Hier der Source Code

Code: Alles auswählen

#xtrans  CenterPos( <aProgSize>, <aRefSize> ) => ;
         { Int( (<aRefSize>\[1] - <aProgSize>\[1]) / 2 ) ;
         , Int( (<aRefSize>\[2] - <aProgSize>\[2]) / 2 ) }

Private oProgDlg    , ;
        aProgSize   := {600,100}  // horizontal

PROCEDURE statusanzeige (nMode, nMin, nMax, fromcol, fromrow, n_width, n_height, cTitle)
Local nColor := 2     // Blau
default cTitle to " "
default fromcol to 0
default fromrow to 0
default n_width to 400
default n_height to 24
default nMax to 100

do case
   case nMode = 0

      oProgDlg := StartProgress(Appdesktop(),aProgSize,nMin,nMax,nColor,cTitle)

   case nMode = 1

      IncProgress(oProgDlg)

   case nMode = 2
      oProgDlg:Destroy()
      oProgDlg:= NIL
      sleep(5)

endcase

RETURN




FUNCTION StartProgress(oParent,aProgSize,nMin,nMax,nColor,cTitle)
LOCAL oDlg  
   IF EMPTY(aProgSize)
      aProgSize := {300,55}
   ENDIF
   oDlg := ProgressDlg():NEW(oParent,,CenterPos(aProgSize,oParent:CurrentSize()),aProgSize)
   oDlg:ProgressBar:minimum := nMin
   oDlg:ProgressBar:maximum := nMax
   IF nColor != NIL
      oDlg:ProgressBar:Color := nColor
   ENDIF   
   oDlg:create()  
RETURN oDlg

PROCEDURE IncProgress(oProgDlg)
   oProgDlg:ProgressBar:increment()
RETURN   


CLASS ProgressDlg FROM XbpDialog
EXPORTED: 
   VAR ProgressBar,Percentage 
   INLINE METHOD INIT(oParent, oOwner, aPos, aProgSize, aPP, lVisible )
       ::XbpDialog:Init(oParent, oOwner, aPos, aProgSize, aPP, lVisible )
       ::TitleBar := .F.
       IF aProgSize[1]>aProgSize[2] // wide use horizontal
          ::ProgressBar:= ProgressBar():New(::XbpDialog,,{10,aProgSize[2]/2-INT(0.3*aProgSize[2])},{aProgSize[1]-20,INT(0.3*aProgSize[2])})
          IF aProgSize[2] >= 50
             ::Percentage := XbpStatic():New(::XbpDialog,,{10,aProgSize[2]-INT(0.5*aProgSize[2])},{aProgSize[1]-20,INT(0.3*aProgSize[2])})
             ::Percentage:Type := XBPSTATIC_TYPE_TEXT
//             ::Percentage:Options := XBPSTATIC_TEXT_CENTER+XBPSTATIC_TEXT_VCENTER
             ::Percentage:Options := XBPSTATIC_TEXT_LEFT+XBPSTATIC_TEXT_VCENTER
             ::ProgressBar:Percent := ::Percentage
          ENDIF
       ELSE
          ::ProgressBar:= ProgressBar():New(::XbpDialog,,{aProgSize[1]/2+INT(0.3*aProgSize[1])/4,10},{INT(0.3*aProgSize[1]),aProgSize[2]-20})
          IF aProgSize[1] >= 50
             ::Percentage := XbpStatic():New(::XbpDialog,,{0,10},{INT(0.5*aProgSize[1]),aProgSize[2]-20})
             ::Percentage:Type := XBPSTATIC_TYPE_TEXT
//             ::Percentage:Options := XBPSTATIC_TEXT_CENTER+XBPSTATIC_TEXT_VCENTER
             ::Percentage:Options := XBPSTATIC_TEXT_CENTER+XBPSTATIC_TEXT_LEFT
             ::ProgressBar:Percent := ::Percentage
          ENDIF
       ENDIF   
   RETURN Self
   INLINE METHOD Create(oParent, oOwner, aPos, aProgSize, aPP, lVisible )
       ::XbpDialog:Create(oParent, oOwner, aPos, aProgSize, aPP, lVisible )
       ::ProgressBar:Create()
       IF !EMPTY(::Percentage)
         ::Percentage:Create()
       ENDIF  
   RETURN Self
   INLINE METHOD Destroy()
       ::ProgressBar:Destroy()
       ::ProgressBar := NIL
       ::XbpDialog:Destroy()
   RETURN Self
ENDCLASS      


CLASS ProgressBar FROM XbpStatic
   PROTECTED:
   VAR    squares, every, _current
   METHOD displayHoriz, displayVert

   EXPORTED:
   VAR           maxWait, color,Thread,sig 
   VAR           minimum, current, maximum
   VAR           Percent  
   ASSIGN METHOD minimum, current, maximum 

   METHOD init   , create , destroy , setSize
   METHOD display, execute, increment
ENDCLASS



/*
 * Initialize the object and set Thread:interval() to zero. This way,
 * method :execute() is automatically repeated.
 */
METHOD ProgressBar:init( oParent, oOwner, aPos, aProgSize, aPP, lVisible )
   ::Thread := Thread():New() // don't inherhit
//   ::Thread:init()
   ::Thread:setInterval( 1 ) // maybe the problem is with interval(0)-nope
   ::Thread:atStart := {|| ::xbpStatic:show() }
   ::Sig := Signal():New()  // don't inherhit
//   ::Signal:init()

   ::xbpStatic:init( oParent, oOwner, aPos, aProgSize, aPP, lVisible )
   ::xbpStatic:type  := XBPSTATIC_TYPE_RAISEDBOX
   ::xbpStatic:paint := {|| ::display() }
   
   ::color   := GRA_CLR_BLUE
   ::squares := 1
   ::current := 0
   ::every   := 1
   ::maxWait := 100
   ::minimum := 0
   ::maximum := 100
RETURN



/*
 * Request system resources; calculate the number or squares which
 * fit into the progress bar and start the thread.
 */
METHOD ProgressBar:create( oParent, oOwner, aPos, aProgSize, aPP, lVisible )
   
   ::xbpStatic:create( oParent, oOwner, aPos, aProgSize, aPP, lVisible )

   aProgSize     := ::currentSize()
   ::squares := Int( aProgSize[1] / (aProgSize[2]+1) )
   ::Thread:start({||::execute()})

RETURN



/*
 * Stop the thread of ProgressBar and release system resources
 */
METHOD ProgressBar:destroy

  /*
   * Turn off automatic repetition of :execute().
   */
   ::thread:setInterVal( NIL )


   IF ::thread:active
     /*
      * Thread is still active.
      * Signal thread to leave its :wait() state
      */
      ::Sig:signal()
   ENDIF


   IF ThreadObject() <> ::thread
     /*
      * The current thread is not the thread of ProgressBar (self).
      * Therefore, the current thread must wait for the end of self:thread
      */
      ::thread:synchronize(0)
   ENDIF


  /*
   * System resources are released when self:thread has terminated
   */
   ::thread := NIL  // bingo this does release the thread!!!!
   ::xbpStatic:destroy()

RETURN self



/*
 * Change the size of ProgressBar. Before the size is changed,
 * everything is overpainted with the background color.
 */
METHOD ProgressBar:setSize( aProgSize )
   LOCAL oPS, aAttr[ GRA_AA_COUNT ], _aProgSize

   oPS       := ::lockPS()
   _aProgSize    := ::currentSize()
   _aProgSize[1] -= 2
   _aProgSize[2] -= 2
   aAttr [ GRA_AA_COLOR ] := GRA_CLR_BACKGROUND
   GraSetAttrArea( oPS, aAttr )
   GraBox( oPS, {1,1}, _aProgSize, GRA_FILL )
   ::unlockPS( oPS )
   ::xbpStatic:setSize( aProgSize )

RETURN self



/*
 * ASSIGN method for :minimum
 */
METHOD ProgressBar:minimum( nMinimum )

   IF ::maximum <> NIL .AND. nMinimum > ::maximum
      ::minimum := ::maximum
      ::maximum := nMinimum
   ELSE
      ::minimum := nMinimum  
   ENDIF

   ::current := ::minimum 
RETURN self



/*
 * ASSIGN method for :current
 */
METHOD ProgressBar:current( nCurrent )

   IF Valtype( nCurrent ) == "N"
      ::current := nCurrent

      IF Valtype( ::maximum ) + Valtype( ::minimum ) == "NN"
         ::every    := Int( ( ::maximum - ::minimum ) / ::squares )
         ::_current := ::current
      ENDIF
   ENDIF

RETURN ::current



/*
 * ASSIGN method for :maximum
 */
METHOD ProgressBar:maximum( nMaximum )

   IF ::minimum <> NIL .AND. nMaximum < ::minimum
      ::maximum := ::minimum
      ::minimum := nMaximum
   ELSE
      ::maximum := nMaximum  
   ENDIF

   ::current := ::minimum 

RETURN self



/*
 * Increment the current value and refresh display if necessary
 */
METHOD ProgressBar:increment( nIncrement )

   IF Valtype( nIncrement ) <> "N"
      nIncrement := 1
   ENDIF

  /*
   * While a progress is displayed, PROTECTED VAR :_current is incremented
   * to avoid the overhead of the ASSIGN method :current()
   */
   ::_current += nIncrement
   

   IF Int( ::_current % ::every ) == 0
     /*
      * This interrupts the ::wait( ::maxWait ) method in :execute().
      * The progress bar is then refreshed immediately in its own thread.
      * Since the display occurs in a separate thread, it does not
      * slow down the actual process whose progress is visualized.
      * Index creation, for example, does not update the display,
      * but only signals self:thread
      */
      ::Sig:signal()
   ENDIF
RETURN



/*
 * Refresh progress bar automatically every ::maxWait / 100 seconds
 * This method runs in self:thread and is automatically restarted
 * due to :setInterval(0)
 */
METHOD ProgressBar:execute

   ::Sig:wait( ::maxWait )
   ::display()

RETURN self



/*
 * Visualize the current state of a process
 */
METHOD ProgressBar:display
   LOCAL oPS   := ::lockPS()
   LOCAL aProgSize := ::currentSize()
   LOCAL aAttr [ GRA_AA_COUNT ]

   aProgSize[1] -= 2
   aProgSize[2] -= 2

   IF aProgSize[1] > aProgSize[2]
      ::displayHoriz( oPS, aProgSize, aAttr )
   ELSE
      ::displayVert ( oPS, aProgSize, aAttr )
   ENDIF
   IF !EMPTY(::Percent)
      ::Percent:SetCaption(STR(INT(100*::_current/(::maximum-::minimum)),3)+"%")
   ENDIF   
   ::unlockPS( oPS )
RETURN self



/*
 * Display squares from left to right (horizontal display)
 */
METHOD ProgressBar:displayHoriz( oPS, aProgSize, aAttr )
   LOCAL nX, aPos1, aPos2, nCenter

  /*
   * Max. x coordinate for squares
   */
   nX := aProgSize[1] * ::_current / ( ::maximum - ::minimum )
   nX := Min( nX, aProgSize[1] )

  /*
   * Fill the area to the right of the squares with background color
   */
   aAttr [ GRA_AA_COLOR ] := GRA_CLR_BACKGROUND
   GraSetAttrArea( oPS, aAttr )
   GraBox( oPS, {1+nX,1}, {aProgSize[1],aProgSize[2]}, GRA_FILL )

  /*
   * Define fill color for squares
   */
   aAttr [ GRA_AA_COLOR ] := ::color
   GraSetAttrArea( oPS, aAttr )

  /*
   * Calculate position for leftmost square (starting position)
   */
   aPos1     := { 2, 2 }   
   ::squares := Int( aProgSize[1] / (aProgSize[2]+1) )
   nCenter   := 2 + ( aProgSize[1] - (::squares * (aProgSize[2]+1)) ) / 2
   aPos1[1]  := Max( 2, nCenter )
   aPos2     := { aPos1[1]+aProgSize[2]-2 , aProgSize[2]-1 }

  /*
   * Draw the squares
   */
   DO WHILE aPos2[1] < nX
      GraBox( oPS, aPos1, aPos2, GRA_FILL )
      aPos1[1] += aProgSize[2]+1
      aPos2[1] += aProgSize[2]+1
   ENDDO

   IF aPos2[1] < aProgSize[1]
      GraBox( oPS, aPos1, aPos2, GRA_FILL )
   ENDIF

RETURN self



/*
 * Display squares from bottom to top (vertical display)
 */
METHOD ProgressBar:displayVert( oPS, aProgSize, aAttr )
   LOCAL nY, aPos1, aPos2, nCenter

  /*
   * Max. y coordinate for squares
   */
   nY := aProgSize[2] * ::_current / ( ::maximum - ::minimum )
   nY := Min( nY, aProgSize[2] )

  /*
   * Fill the area above the squares with background color
   */
   aAttr [ GRA_AA_COLOR ] := GRA_CLR_BACKGROUND
   GraSetAttrArea( oPS, aAttr )
   GraBox( oPS, {1,nY}, {aProgSize[1],aProgSize[2]}, GRA_FILL )

  /*
   * Define fill color for squares
   */
   aAttr [ GRA_AA_COLOR ] := ::color
   GraSetAttrArea( oPS, aAttr )

  /*
   * Calculate position for lowest square (starting position)
   */
   aPos1     := { 2, 2 }   
   ::squares := Int( aProgSize[2] / (aProgSize[1]+1) )
   nCenter   := 2 + (aProgSize[2] - (::squares * (aProgSize[1]+1)) ) / 2
   aPos1[2]  := Max( 2, nCenter )
   aPos2     := { aProgSize[1]-1, aPos1[2]+aProgSize[1]-2 }

  /*
   * Draw the squares
   */
   DO WHILE aPos2[2] < nY
      GraBox( oPS, aPos1, aPos2, GRA_FILL )
      aPos1[2] += aProgSize[1]+1
      aPos2[2] += aProgSize[1]+1
   ENDDO

   IF aPos2[2] < aProgSize[2]
      GraBox( oPS, aPos1, aPos2, GRA_FILL )
   ENDIF

RETURN self


Zuletzt geändert von Koverhage am Do, 06. Aug 2009 17:18, insgesamt 1-mal geändert.
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: Progressbar

Beitrag von brandelh »

Hallo Klaus,

die Funktion StartProgress(oParent,aProgSize,nMin,nMax,nColor,cTitle)
erhält den cTitle ich denke um den geht es.
Diese erzeugt dann ein Objekt des Prozentanzeigefensters ... mit den Standardparametern wird automatisch ( ...:New(...) ) :init(...) aufgerufen
und dort wird die Ausrichtung festgelegt, aber solange create nicht ausgeführt ist, kann man dies einfach überschreiben.

Entweder du erzeugst eine ::cTitle Instanzvariable (wenn der Titel auch später benötigt wird), übergibst dieser cTitle und nimmst diese zum Steuern in create VOR dem Aufruf der Superklasse, oder wenn man es dort nicht braucht, reicht auch das Setzen in der aufrufenden Funktion:

Code: Alles auswählen

FUNCTION StartProgress(oParent,aProgSize,nMin,nMax,nColor,cTitle)
LOCAL oDlg     IF EMPTY(aProgSize)
      aProgSize := {300,55}
   ENDIF
   oDlg := ProgressDlg():NEW(oParent,,;
           CenterPos(aProgSize,oParent:CurrentSize()) ,aProgSize)
   oDlg:ProgressBar:minimum := nMin
   oDlg:ProgressBar:maximum := nMax

   // wenn wir cTitle nicht mehr brauchen reicht das ...
   if empty(cTitle)
      oDlg:Percentage:Options := ;
           XBPSTATIC_TEXT_CENTER+XBPSTATIC_TEXT_VCENTER
   else
      oDlg:Percentage:Options := ;
           XBPSTATIC_TEXT_LEFT+XBPSTATIC_TEXT_VCENTER
   endif

   // aber wir brauchen cTitle ja für den Text in 333ff, also noch:
   oDlg:cTitle := cTitle

   IF nColor != NIL
      oDlg:ProgressBar:Color := nColor
   ENDIF      
   oDlg:create()  
RETURN oDlg
und in der Klasse ...

Code: Alles auswählen

CLASS ProgressDlg FROM XbpDialog
EXPORTED:    VAR ProgressBar,Percentage,cTitle
   INLINE METHOD INIT(oParent, oOwner, aPos, aProgSize, aPP, lVisible )
       ::cTitle := ""
       ::XbpDialog:Init(oParent, oOwner, aPos, aProgSize, aPP, lVisible )
       ::TitleBar := .F.
...
im Text dann bei 333 wie gewünscht, aber auf ::cTitle zugreifen !

man hätte natürlich auch den neuen Parameter am Ende des Aufrufs von INIT und NEW anhängen und dann dort an ::cTitle übergeben können inkl. Steuerung, aber wenn man sich mit den Komma vertippt, dann ist das riskanter.

Sauberer wäre natürlich nicht die Variable nach außen zu geben, sondern alles zu kapseln, aber solange man das nur selbst nutzt ... 8)
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: Progressbar

Beitrag von Koverhage »

Hubert,

erstmal danke, wie bekomme ich den Text (cTitle) nach ProgressBar:display ?

Wo muss ich da die Variable definieren ?
Gruß
Klaus
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: Progressbar

Beitrag von Koverhage »

geschafft.
Habe in der Class ProgressBar auch die Variable cTitle angelegt
und in StartProgress diese übergeben

oDlg:ProgressBar:cTitle := cTitle


CLASS ProgressBar FROM XbpStatic
PROTECTED:
VAR squares, every, _current
METHOD displayHoriz, displayVert

EXPORTED:
VAR maxWait, color,Thread,sig
VAR minimum, current, maximum
VAR Percent, cTitle
ASSIGN METHOD minimum, current, maximum

METHOD init , create , destroy , setSize
METHOD display, execute, increment
ENDCLASS



/*
* Initialize the object and set Thread:interval() to zero. This way,
* method :execute() is automatically repeated.
*/
METHOD ProgressBar:init( oParent, oOwner, aPos, aProgSize, aPP, lVisible )
::Thread := Thread():New() // don't inherhit
// ::Thread:init()
::Thread:setInterval( 1 ) // maybe the problem is with interval(0)-nope
::Thread:atStart := {|| ::xbpStatic:show() }
::Sig := Signal():New() // don't inherhit
// ::Signal:init()

::xbpStatic:init( oParent, oOwner, aPos, aProgSize, aPP, lVisible )
::xbpStatic:type := XBPSTATIC_TYPE_RAISEDBOX
::xbpStatic:paint := {|| ::display() }

::color := GRA_CLR_BLUE
::squares := 1
::current := 0
::every := 1
::maxWait := 100
::minimum := 0
::maximum := 100
::cTitle := ""
RETURN
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: Progressbar

Beitrag von brandelh »

Koverhage hat geschrieben:geschafft.
Habe in der Class ProgressBar auch die Variable cTitle angelegt
und in StartProgress diese übergeben

oDlg:ProgressBar:cTitle := cTitle
Das hatte ich eigentlich gemeint und dann in der Eile beim Kopieren vergessen die ProgressBar dazwischen zu hängen.

Da du es selbst gelöst hast ist aber sicher besser :D
Gruß
Hubert
Antworten