Page 1 of 3

TGRAPH Repopulate

Posted: Wed Jun 25, 2014 8:14 am
by Jack
Hello,
I have a dialog with a Listbox and a Tgraph .

When i select an other line in the Listbox, i 'd like to repopulate the graph with the values of other records .

How to change the values of the graph ?

Thanks

Re: TGRAPH Repopulate

Posted: Wed Jun 25, 2014 12:20 pm
by Antonio Linares
Jack,

Could you provide a small example using your code ? This way we can modify it and show you how to do it, thanks! :-)

Re: TGRAPH Repopulate

Posted: Wed Jun 25, 2014 3:14 pm
by Jack
Antonio,

I don't know how to change the array ASERIES .

Here is a sample of code :
*
REDEFINE LISTBOX oLbxta FIELDS ID 200 of oDlgrh
REDEFINE GRAPH oGraf OF odlgrh ID 300 TITLE "Evolution" XGRID YGRID XVALUES YVALUES LEGENDS TYPE 2
oGraf:cTitle := "Historique de "+trim(wrh->lib)
oGraf:cSubTit:= "Seconde zone de titre"
oGraf:cTitX := "Demandes"
oGraf:cTitY := "Valeurs"
* oGraf:lPopUp := .T.
oGraf:AddSerie(aSerie, "Valeurs", RGB(128,128,255))
oGraf:SetYVals(aLeyen)

oLbxta:bChange := { || oGraf:cTitle:=trim(wrh->lib),??? here to place the code to repopulate ???,oGraf:Refresh() }

ACTIVATE DIALOG oDlgrh CENTERED

Re: TGRAPH Repopulate

Posted: Wed Jun 25, 2014 7:42 pm
by James Bott
The easiest way would be to just kill the entire graph object and build a new one. This is probably not the most efficient, however.

James

Re: TGRAPH Repopulate

Posted: Wed Jun 25, 2014 7:47 pm
by James Bott
I just looked at the TGraph code and there are no methods to delete a series of data. Adding such a method would require a fair amount of programming.

James

Re: TGRAPH Repopulate

Posted: Thu Jun 26, 2014 1:38 am
by nageswaragunupudi
Jack wrote:Hello,
I have a dialog with a Listbox and a Tgraph .

When i select an other line in the Listbox, i 'd like to repopulate the graph with the values of other records .

How to change the values of the graph ?

Thanks
oGraph:aData contains an array of values. On change of record, just repopulate the array oGraph:aData with new values and call oGraph:Refresh(). It is that simple.

oGraph:aData is a multi-dimensional array. Each element of the array is an array of values for each series.

{ { <series-1 values,,,,,> }, ;
{ <series-2 values,,,,,> }, ;
etc
}

Here is a self-contained working example using TXBrowse and TGraph.

Code: Select all

#include "fivewin.ch"
#include "tgraph.ch"

REQUEST DBFCDX

function main()

   local oDlg, oBrw, oGraph, oFont

   CreateTestDBF()  // Creates test DBF and opens with Alias "SC"

   DEFINE FONT oFont NAME "TAHOMA" SIZE 0,-14
   DEFINE DIALOG oDlg SIZE 900,340 PIXEL FONT oFont ;
      TITLE "XBROWSE LINKED GRAPH"

   @ 10,10 XBROWSE oBrw SIZE 210,150 PIXEL OF oDlg ;
      DATASOURCE "SC" AUTOCOLS ;
      HEADERS "MONTH", "USA", "EUROPE", "ASIA", "USA", "EUROPE", "ASIA" ;
      FASTEDIT LINES NOBORDER

   WITH OBJECT oBrw
      :lHScroll         := .f.
      :lVScroll         := .f.
      :nStretchCol      := 1
      :nMarqueeStyle    := MARQSTYLE_HIGHLROW
      :bClrRowFocus     := { || { CLR_BLACK, RGB(185,220,255) } }
      :cEditPictures    := "9,999"
      :aCols[ 1 ]:cEditPicture := nil
      :SetGroupHeader( "SALES", 2, 4 )
      :SetGroupHeader( "COSTS", 5, 7 )
      :bChange := { || oGraph:cTitY := SC->MONTH, ;
                       oGraph:aData := { { SC->USAS, SC->EUROS, SC->ASIAS }, ;
                                         { SC->USAC, SC->EUROC, SC->ASIAC } }, ;
                       oGraph:Refresh() }
      AEval( :aCols, { |o| o:nEditType := EDIT_GET, ;
                           o:bOnChange := ;
                              { |oc| oGraph:aData[ Int( ( oc:nCreationOrder - 2 ) / 3 ) + 1, ;
                                                   ( oc:nCreationOrder - 2 ) % 3 + 1 ;
                                                 ] := oc:Value, ;
                                                oGraph:Refresh() } ;
                     }, 2 )
      //
      :CreateFromCode()
   END

   @ 10,220 GRAPH oGraph SIZE 200,150 PIXEL OF oDlg ;
      TITLE "Sales and Costs" ;
      XVALUES YVALUES TYPE GRAPH_TYPE_BAR LEGENDS

   oGraph:cTitY      := SC->MONTH
   ADD SERIE TO oGraph SERIE { SC->USAS, SC->EUROS, SC->ASIAS } LEGEND "Sales" COLOR CLR_HRED
   ADD SERIE TO oGraph SERIE { SC->USAC, SC->EUROC, SC->ASIAC } LEGEND "Costs" COLOR CLR_GREEN

   SET Y LABELS OF oGraph TO { "USA", "EUROPE", "ASIA" }

   oGraph:nMaxVal    := 2000

   ACTIVATE DIALOG oDlg CENTERED
   RELEASE FONT oFont

return nil

static function CreateTestDBF()

   local aCols := {  ;
      { "MONTH",     'C',  3, 0  }, ;
      { "USAS",      'N',  4, 0  }, ;
      { "EUROS",     'N',  4, 0  }, ;
      { "ASIAS",     'N',  4, 0  }, ;
      { "USAC",      'N',  4, 0  }, ;
      { "EUROC",     'N',  4, 0  }, ;
      { "ASIAC",     'N',  4, 0  }  }

   local aData := {  { "JAN", 1000, 1200,  900,  400,  700,  400 },  ;
                     { "FEB", 1100, 1300, 1000,  500,  800,  500 },  ;
                     { "MAR", 1050, 1800, 1900,  700, 1400, 1600 }   ;
                  }

   DBCREATE( "SALECOST.DBF", aCols, "DBFCDX", .t., "SC" )
   FW_ArrayToDBF( aData )
   GO TOP

return nil
 
In the above example, the code which re-populates the graph and repaints is:

Code: Select all

      :bChange := { || oGraph:cTitY := SC->MONTH, ;
                       oGraph:aData := { { SC->USAS, SC->EUROS, SC->ASIAS }, ;
                                         { SC->USAC, SC->EUROC, SC->ASIAC } }, ;
                       oGraph:Refresh() }
 
You need to adopt this part of the code to suit your data.

Screen-shot when user is on the first row:
Image

Screen-shot when the user moved to the last row:
Image

I guess this is what you want to do.

Re: TGRAPH Repopulate

Posted: Thu Jun 26, 2014 5:11 am
by Otto
WOW sensational

Best regards,
Otto

Re: TGRAPH Repopulate

Posted: Thu Jun 26, 2014 7:43 am
by Enrico Maria Giordano
Great sample!

EMG

Re: TGRAPH Repopulate

Posted: Thu Jun 26, 2014 10:42 am
by Jack
Thanks a lot ,
It is just what I was looking for !

Thanks

Re: TGRAPH Repopulate

Posted: Thu Jun 26, 2014 11:27 am
by ukoenig
Maybe possible to change optional the GRADIENT-direction ?
Using a 3 way-status : 0 = NO gradient, 1 = gradient horiz., 2 = gradient vert.

oGraph:nDegrade := 0

in Method _FillRect :

IF ::nDegrade > 0
IF ::nDegrade = 1
nMid:=(nRight-nLeft)/2
Gradient( ::hDC, { nTop, nLeft, nBottom, nRight-nMid }, nColor, LightColor(175,nColor), .F. )
// .T. = Vertical
Gradient( ::hDC, { nTop, nLeft+nMid, nBottom, nRight }, LightColor(175,nColor), nColor, .F. )

ELSE
????????
ENDIF
ELSE
FillRect( ::hDC, { nTop, nLeft, nBottom, nRight }, hBru )
ENDIF

Image

Image

Best regards
Uwe :?:

Re: TGRAPH Repopulate

Posted: Thu Jun 26, 2014 12:43 pm
by nageswaragunupudi
Mr Uwe

The second graph is very nice.
Can you please suggest revised code?

Re: TGRAPH Repopulate

Posted: Thu Jun 26, 2014 1:16 pm
by nageswaragunupudi
I modified the above code to provide for editing of values in the browse. When a value in the browse is modified, the corresponding value in the oGraph:aData is modified and the graph is refreshed.

My intention is to keep on record the possibilities of dynamic updating of TGraph.

Re: TGRAPH Repopulate

Posted: Thu Jun 26, 2014 2:47 pm
by ukoenig
Mr. Rao,

Defined :

oGraph:nMaxVal := 2000
oGraph:nDegrade := 2
oGraph:nClrBack := 16443068

The changes / replacements :
I still have to check the wrong background-painting


1. DATA nDegrade // Degrade bars color 0, 1, 2
2. ::nDegrade := 0 // default
3. IF ::nDegrade > 0 // Gradient
4. IF ::!lDegrade to be changed in IF ::nDegrade = 0
5. IF ::lDegrade to be changed in IF ::nDegrade > 0
6. in popmenu
"&No Degrade", ;
"&Degrade horiz.", ;
"&Degrade vert.", ;
7. in Method _FillRect


hBru := CreateSolidBrush( nColor )
hOld := SelectObject( ::hDC, hBru )
IF ::nDegrade > 0
IF ::nDegrade = 1
nMid:=(nRight-nLeft)/2
Gradient( ::hDC, { nTop, nLeft, nBottom, nRight-nMid }, nColor, LightColor(175,nColor), .F. )
Gradient( ::hDC, { nTop, nLeft+nMid, nBottom, nRight }, LightColor(175,nColor), nColor, .F. )
ELSE
hBru = GradientBrush( ::hDC, 0, 0, 0, nTop, { { 0, nColor, LightColor(175,nColor) } }, .T. )
FillRect( ::hDC, { nTop, nLeft, nBottom, nRight }, hBru )
ENDIF
ELSE
FillRect( ::hDC, { nTop, nLeft, nBottom, nRight }, hBru )
ENDIF


Image

Best regards
Uwe :lol:

Re: TGRAPH Repopulate

Posted: Thu Jun 26, 2014 4:03 pm
by ukoenig
The added background-section :
A higher graph shows a better vertical-gradient

hBru = GradientBrush( ::hDC, 0, 0, 0, nBottom-nDeep, ;
{ { 0, ::nClrBack, LightColor(175,::nClrBack) } }, .T. )
FillRect( ::hDC,{ nTop, nLeft, nBottom-nDeep , nRight }, hBru )


Image

Code: Select all

// Back area
//
IF ! Empty( ::cBitmap ) .AND. File( AnsiToOem( Lfn2Sfn( ::cBitmap ) ) )
     ::SayBitmap( 0, 0, AnsiToOem( Lfn2Sfn( ::cBitmap ) ), ::nWidth, ::nHeight )
ELSEIF Empty( ::oPrn ) .AND. ::nType != GRAPH_TYPE_PIE
     IF ::nDegrade = 1
          ::FillRect( nTop, nLeft, nBottom-nDeep, nRight, ::nClrBack )
     ELSE
          hBru = GradientBrush( ::hDC, 0, 0, 0, nBottom-nDeep, ; 
               { { 0, ::nClrBack, LightColor(175,::nClrBack) } }, .T. )
          FillRect( ::hDC,{ nTop, nLeft, nBottom-nDeep , nRight }, hBru )     
     ENDIF
ENDIF
 

Re: TGRAPH Repopulate

Posted: Thu Jun 26, 2014 6:39 pm
by ukoenig
Maybe another change, tested using a background-image :
keep the background of the bar-area.
( could be optional ) ?

Image

Code: Select all

// Back area
//
IF ! Empty( ::cBitmap ) .AND. File( AnsiToOem( Lfn2Sfn( ::cBitmap ) ) )
     ::SayBitmap( 0, 0, AnsiToOem( Lfn2Sfn( ::cBitmap ) ), ::nWidth, ::nHeight )
     IF ::nDegrade = 1
           ::FillRect( nTop, nLeft, nBottom-nDeep, nRight, ::nClrBack )
     ELSE
          hBru = GradientBrush( ::hDC, 0, 0, 0, nBottom-nDeep, ; 
                { { 0, ::nClrBack, LightColor(175,::nClrBack) } }, .T. )
          FillRect( ::hDC,{ nTop, nLeft, nBottom-nDeep , nRight }, hBru )
     ENDIF  
ELSEIF Empty( ::oPrn ) .AND. ::nType != GRAPH_TYPE_PIE 
     IF ::nDegrade = 1
          ::FillRect( nTop, nLeft, nBottom-nDeep, nRight, ::nClrBack )
     ELSE
          hBru = GradientBrush( ::hDC, 0, 0, 0, nBottom-nDeep, ; 
                 { { 0, ::nClrBack, LightColor(175,::nClrBack) } }, .T. )
          FillRect( ::hDC,{ nTop, nLeft, nBottom-nDeep , nRight }, hBru )
    ENDIF
ENDIF
 
Best regards
Uwe :?: