Newsgroup: it.comp.lang.delphi
Titolo: Ritorno del valore in DataTime in un Chart

Buongiorno a tutti
da un Chart avrei bisogno di farmi ritornale al passaggio del mouse su una "FastLine" il valore dell'asse "X" in formato di datatime (in quanto il mio chart sull'asse "X" ho l'ora ) mentre riesco solo ad avere il valore assoluto del punto in cui si trova sul grafico.
FACCIO UN ESEMPIO Per l'asse "Y" va bene, mi torna il valore numerico ma sulla "X" il valore mumerico ossia se campiano a 1 secondo se vato dul dato che corrisponde a 1 minuto e 15 secondi il valore letto 75. Penso ci sia giù il modo di farmi restituire il valore in tempo ma non so quale sia.
 
Grazie per eventuali suggerimenti


Ciao Ruby,
   hai tralasciato il componente che usi.
TeeChart, TMS chart o altri ?
Io ho usato solo i teechart e i tms chart, entrambi hanno punti di forza 
e punti deboli.
tornando al tuo problema, credo che la soluzione a te piu' appropriata 
sia come tu configuri gli assi e come vuoi che appaia la scala delle 
ascisse e come pensi di visualizzare i dati sulle ordinate.
Esempio pratico
Y = Scala da 0..1000
X = Scala in TDatetime da 01/04/2021 00.00 a 16/04/2021 10.00
 
Visualizzi il grafico con delle linee a secondo dei valori da 0..1000 ad 
intervalli di 15 minuti (x), dato che sulle X hai TDatetime (e il tuo 
componente lo permette) visualizzi solo la parte time ed, al bisogno, 
estrai la parte Date.
 
Alla prossima
 
Ciao
Daniele

Ciao.
Puoi postare il codice che usi per definire assi e serie?
 
 
A.

 Puoi postare il codice che usi per definire assi e serie?
 
Ecco parte del codicillo..
Questo grafico usa le librerie Steema TeeChart free fornite con le varie 
versioni di delphi.
 
Cht1    : TChart;
LM1     : TLineSeries;
BM1     : TBarSeries;
MyAxis  : TChartAxis; // E' un asse secondario ..
 
Cht1 viene generato auomaticamente
Nella oncreate della form ...
 
LM1:=TLineSeries.Create(Self);
BM1:=TBarSeries.Create(Self);
LM1.ParentChart:=Cht1;
BM1.ParentChart:=Cht1;
Cht1.LeftAxis.Minimum:=1;
Cht1.LeftAxis.Maximum:=YMese;
Cht1.BottomAxis.Axis.Color:=clGreen;
Cht1.CustomAxes.Add;
Cht1.CustomAxes[0].Horizontal:=True;
Cht1.CustomAxes[0].Axis.Color:=clRed;
Cht1.CustomAxes[0].PositionPercent:=-30;
Cht1.CustomAxes[0].Automatic:=True;
Cht1.CustomAxes[0].AutomaticMaximum:=True;
Cht1.CustomAxes[0].AutomaticMinimum:=True;
 
Quando popolo il grafico filtro il db per mese e per anno, inoltre nel 
record del db si trova il campo giorno.
Anno Mese Giorno sono definti come Word
 
Il grafio e' popolato con
 
LM1.AddXY(X,Y,IntToStr(A),Colore);
 
dove
X e' il punto del grafico (primo, secondo terzo ecc...)
Y e' il valore monetario (1250,35)
IntToStr(A) e' il valore numerico del giorno, la label che viene messa 
sotto il punto
Colore e' il colore del tratto del segmento del grafico.
 
Inoltre, l'ascissa e' settata con
 
Cht1.BottomAxis.Maximum:=DaysInMonth(Cal1.Year,Cal1.Month);
Cht1.BottomAxis.Minimum:=1;
Cht1.BottomAxis.Title.Caption:= xxx // Titolo dell'asse
 
Cal1 e' un componente calendario
 
Le librerie TMS mettono a disposizione diversi compopnenti per i 
grafici, quello suggerito da loro per lavorare con le data e' nelle 
librerie FNC.
 
Non e' per niente facile lavorare con nessuno di questi ..... perche' a 
ounti di forza si contrappongono punti deboli assai piu' incisivi dei 
punti di foza.
Teechart e tms vclchart (chiamiamolo cosi') non permettono di lavorare 
con i giorni sule ascisse se non con artifici vari (per esempio un array 
di record in cui registrare il punto con il giorno in formato tdate(time)).
L'altro, il fncchart, permette di avere i giorni sulle ascisse in 
formato tdate(time) ma (come nel mio caso) se si hanno piu' serie 
(quindi piu' valori di "giorno" e piu' valori "currency" sull Y, si deve 
decire quale delle 2 tenere come riferimento principale (nel mio caso le 
X) e l'altro asse risulta sfalsato ovvero ho 2 assi Y con valori diversi).
 
Ad oggi non ho trovato nessuna risoluzione completa alle mie necessita' 
ma soltanto dei compromessi.
Sto valutando se sostituire il teechat con il fncchart ma i primi 
risultati *NON* sono incoraggianti !!
 
Tornando a noi, non credo sia quello che volevi, o stavi cercando.
Mi spiace ...
 
Ciao
 
Daniele
 
PS: mi sono dilungato un po .. scusami ..
 
 
 
 
 
 
 

 risultati *NON* sono incoraggianti !! 
 
Uso delphi da più di 20 anni e non ho mai sentito di alternative a TeeChart.
Magari ci sono e magari sono migliori, ma questa tua frase non fa altro che rafforzare l'idea che è meglio non uscire dal seminato.
 
A.

 Magari ci sono e magari sono migliori, ma questa tua frase non fa altro che rafforzare l'idea che è meglio non uscire dal seminato.
Il componente per grafici della TMS e' partito con le idee giuste.
Peccato che quando qualche utente (a dire il vero tanti) chiedono di 
apportare miglioramenti e non lo fai perche' hai altro da fare o, nella 
peggiore delle risposte, il componente va gia' bene cosi' .... capisci 
che la strada non e' piu' quella giusta.
Ed e' per quello che continuo ad usare il TeeChart ....
 
Un caro saluto
 
Ciao
Daniele
 

 che la strada non e' piu' quella giusta. 
 
Mollare prima di subito.
 
 
 
A.


Scusa Daniel, se non ho dato dettagli e se non ho risposto in modo celere
Uso il componente TeeChart, ho un archivio si dati che deriva da un CSV dove registro dei valori per 24 ore ogni 2 secondi (per cui circa 43200) punti sull'asse X con scritto 12:00:00 - 12:00:02 - 12:00:04 - 12:00:06 ecc dalla mezza notte 00:00:00 a 23:59:58 . Effettivamente io leggo il valore dei punti, per cui se tutti i grafici fossero campionati a 2 secondi non sarebbe difficile fare una conversione in tempo (ora / min / sec) ma se mi capita un campionamento a 3' 30'' la cosa non regge più, per cui volevo sapere se potevo avere in risultato del valore reale scritto sull'asse "X" anziche il punto in cui passo il mouse.
Ora leggo le varie risposte che mi avete dato, magari c'è gia la soluzione.


Alberto ti giro una piccola parte del codice, perchè le serie sono molte e vengono ripetute per 43200 volte, nella variabile ora scrivo la stringa dell'ora relativa (es 12:00:00 - 12:00:02 ecc)
 
      if Serie0 = '' then exit else
       try
        Form1.Series1.Add(Strtofloat(Serie0),Ora,0);
         except
          on E: EConvertError do
           begin
            Serie0 := Serie0_old;
            Form1.Series1.Add(Strtofloat(Serie0),Ora,0);
           end;
       end;
       Serie0_old := Serie0;
 
      if Serie1 = '' then exit else
       try
        Form1.Series2.Add(Strtofloat(Serie1),Ora,0);
        except
          on E: EConvertError do
           begin
            Serie1 := Serie1_old;
            Form1.Series2.Add(Strtofloat(Serie1),Ora,0);
           end;
       end;
       Serie1_old := Serie1;
 
desto codice viene ripetuto per circa 20 serie e le 20 serie sono ripetute per 43200 volte cosi genero il mio grafico.

 on E: EConvertError do 
 
In questo modo se una eventuale eccezione no è di classe EConvertError, avrai un eccezione a runtime.
 
Ho scritto 2 righe veloci in un attimo di pausa. Al click di un TButton, popolo una serie con dei valori di prova:
 
 
 
procedure TForm1.Button1Click(Sender: TObject);
var
  currentdatetime: TDateTime;
  pointindex: integer;
  valore: single;
 
begin
 
  pointindex := 0;
  currentdatetime := now;
 
  while true do begin
    inc(pointindex);
    if (pointindex > 10) then begin
      break;
    end;
    currentdatetime := IncSecond(currentdatetime, 5);
    valore := (pointindex * 1000)/3;
    Series1.AddXY(currentdatetime, valore, IntToStr(pointindex));
  end;
 
//
end;
 
Notare l'uso di ADDXY invece del tuo "add" semplice oltre al fatto di avere il datetime sulle ASCISSE e non sulle ordinate.
 
Poi, per mostrare qualcosa quando L'UTENTE MUOVE IL MOUSE SUL GRAFICO:
 
procedure TForm1.Chart1MouseMove(Sender: TObject; Shift: TShiftState; X,   Y: Integer);
var
  ora: double;
 
  valore: double;
begin
  Series1.GetCursorValues(ora, valore);
  chart1.Hint := 'x=' + DateTimeToStr(ora) + ' y=' + FloatToStr(valore) ;
 
end;
 
GetCursorValues ti restituisce i valori x,y alla posizione corrente del mouse.
Dopodichè, assegni la property Hint del tchart.
Notare la conversione secca basata su datetimetostr che è ovviamente SBAGLIATA ma sono di fretta. Meglio un formatdatetime.
Una possibile alternativa è non usare Hint del tchart ma valorizzare 2 tedit con i valorI restituiti da GetCursorValues.
Nota: questo codice NON GESTISCE il caso in cui GetCursorValues restituisca valori cinofallici, ad esempio se non sei su un punto.
Ma ripeto, avevo solo 5 minuti.
 
Ovviamente (ma non per tutti), se in AddXY passi prima il valore e DOPO l'orario, occorre scambiare di posto le due variabili nella chiamata a GetCursorValues.
 
 
A.


Signori se vi può essere di aiuto l'ho risolta nel seguento modo:
 
procedure TForm1.GraficoRubyMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  XVal: double;
  YVal: double;
begin
  if Memo1.Lines.Count >= 5 then   // verifico di avere almeno 5 campionamenti
   begin
    XVal:=GraficoRuby.Axes.Bottom.CalcPosPoint(X);
    YVal:=GraficoRuby.Axes.Left.CalcPosPoint(Y);
    EditX.Text := Timetostr(XVal / Memo1.Lines.Count);
    EditY.Text := Floattostr (YVal);
   end;
end;
 
Il memo1 è dove scrivo tutti i miei dati.
Faccio un esempio, se campiono una volta al secondo per 24 ore sono 86400 secondi, per cui le linee del mio Memo 1 = 86400 secondi
La funzione "Axes.Bottom.CalcPosPoint(X)" mi ritorna (anche facendo lo zoom) il punto estto delle X mantiene la posizione assoluta e con la conversione "Time tostr" mi converte i secondi in ora esatta.
Se avessi campioanto a 2 secondi il conteggio del Memo 1  sarebbe stao uguale a 43200 seconfi ecc......
Spero di essere stato sufficientemente chiaro nella spiegazione
 
Cordiali saluti DelphiRuby.


Alberto Salvati
Se non sbaglio, la funzione setcursorvalue ritorna in punti la posizione assoluta del mouse sul piano del Chart, ma se fai uno zoom di 300 volte il reale ti sfalsa il valore , mentre " Axes.Bottom.CalcPosPoint(X)" mantiene il valore assoluto relativo all'asse "X".
 
Comunque grazie a tutti ho arricchito le mie conoscenze leggendo i vostri suggerimenti.
 
IL SAPERE APPARTIENE AL MONDO (Saluti DelphiRuby)

mantiene il valore assoluto relativo all'asse "X". 
 
Non ho approfondito. ero di fretta.
 
A.