Tdbchart e gantt

di il
16 risposte

Tdbchart e gantt

Buongiorno a tutti, vorrei chiedervi aiuto su come poter ottenere un grafico gantt usando il tdbchart.

partendo da un dataset che è una tabella che potrebbe avere questi dati:

start | valore|
-----------------
8:00 | 1
9:00 | 2
10:00 | 3
11:00 | 1
12:00 | 2
13:00 | 3

io vorrei avere una riga sola in cui sull asse delle x ho gli orari e sulla riga vorrei arrivare ad avere
un pezzo colorato di giallo (valore 1) dalle 8 alle 9;
un pezzo colorato di blu (valore 2) dalle 9 alle 10;
un pezzo colorato di verde (valore 3) dalle 10 alle 11;
un pezzo colorato di giallo (valore 1) dalle 11 alle 12;
un pezzo colorato di blu (valore 2) dalle 12 alle 13;
un pezzo colorato di verde (valore 3) dalle 13 alle (now) o eventuale filtro data;

ho messo un dbchart sulla form;
ho creato una serie di tipo gantt;
creato datamodule con connessione
creato una query del tipo "select start,valore from table order by start"
ho dato in pasto la query al dataset delle serie gantt ma non riesco ad ottenere quello che vorrei.
Ho visto nelle opzioni della series sotto dataset mi chiede:

- labels: ho messo il campo valore;
- start: ho messo il campo start;
- Y: in realtà non so cosa mettere ( immagino cmq un valore uguale per tutti i record, se voglio ottenere una riga sola e non 6 come nell esempio)
- end: io qui non ho un campo end, al limite potrebbe essere il valore start della riga sucessiva(ma nel db non lo ho, e in effetti con una query non so come poterlo recuperare);

comunque cosi facendo o mi fa vedere 6 righe, oppure una (mettendo un valore 1 all'opzione Y di cui sopra) ma tutta di un colore unica.

qualcuno riesce a darmi qualche suggerimento?
grazie.

16 Risposte

  • Re: Tdbchart e gantt

    C'è qualcosa che mi sfugge, ma non mi è molto chiaro quello che stai cercando di ottenere e la modalità con cui stai passando i dati della Serie, che mi pare incompatibile con la visualizzazione della serie stessa.

    Posta un po' di codice, la versione attuale del grafico e quello che invece dovrebbe essere il risultato atteso.
  • Re: Tdbchart e gantt

    Ti ringrazio molto per l' attenzione,
    Al di la del codice mi sa che i miei problemi partono un po prima, dal capire come fuziona ll'oggetto db chart (non l ho mai usato).

    Cerco di postare quello che ho "fatto":
    nelle opzioni della serie gantt vedo questo: dove "TS" è il campo "start" dell'esempio;
    "num" nel campo "Y" SONO I VALORI 1,2,3,

    il risultato della mia query "SELECT TS,NUM FROM TABLE ORDER BY TS" è:

    8:00 - 1
    9:00 - 2
    10:00 - 3
    11:00 - 1
    12:00 - 2
    13:00 - 3
    in pratica rappresenta uno "stato" (non Nazione ) in cui si trova una macchina:
    dalle 8 alle nove si trova nello stato 1
    dalle 9 alle 10 si trova nello stato 2
    dalle 10 alle 11 si trova nello stato 3
    dalle 11 alle 12 torna a trovarsi nello stato 1
    dalle 12 alle 13 torna a trovarsi nello stato 2
    dalle 13 alle ( non lo so, essendo l ultima riga ma tendenzialmente vuol dire che da quel momento fino ad ora è ancoranello stato 1)

    quello che vorrei avere nel grafica gantt è questo: aggiungendo i dati a mano riesco ( piu o meno) ad ottenere quello che vorrei, anche se come label sull'asse a sinistra mi scrive l ultimo valore e come legenda vorrei avere "solo" l' indicazione :
    quadrato rosa = stato1
    quadrato giallo = stato 2
    quadrato blu = stato 3

    insomma solo ad indicare cosa indicano i colori e non tutti i valori con gli orari, anche perche poi a me servono altri gantt uguali indicanti lo stato di altre macchine.

    ma quello che ottengo dando in pasto la query piuttosto che scrivendo a mano i valori è questo:
    impostando invece la serie cosi: quindi togliendo il valore di Y
    mi viene un grafico cosi' :
    mi manca quindi qualche pezzo, non capisco:
    come mai tutte le righe partono dalle 8 se lo "start" parte dalle 8 solo per lo stato 1?
    se passo col mouse sopra una riga della legenda, al grafico relativo mi "aggiunge" un pezzettino.

    Ho altre domande ma credo che il primo passo sia riuscire ad ottenere quel gantt come da dati manuali.
    Immagino che per metterli tutti sulla stessa riga debba ciclare cmq il gantt da codice ed assegnare ad 1(ocmq uno stesso valore) all'asse Y, una cosa tipo:
        for i := 0 to Series1.Count do
        begin
         Series1.YValue[i]:=1;
       end;
    
    ma quello che ottengo è una riga lunga dalle 8 alle 13 del colore di stato 3.

    insomma sono un attimo in alto mare
  • Re: Tdbchart e gantt

    ziobacco ha scritto:


    Al di la del codice mi sa che i miei problemi partono un po prima, dal capire come fuziona ll'oggetto db chart (non l ho mai usato).
    E' molto semplice: si aggiungono tante Serie configurate nel modo opportuno in base all'aspetto del grafico e ai dati da visualizzare.

    Ogni Serie appartiene a un tipo diverso con metodi differenti per inserire le informazioni relative a punti, barre o altro, a seconda della tipologia del grafico.

    ziobacco ha scritto:


    aggiungendo i dati a mano riesco ( piu o meno) ad ottenere quello che vorrei
    [...]ma quello che ottengo dando in pasto la query piuttosto che scrivendo a mano i valori è questo
    Direi che il problema è questo: i dati provenienti direttamente dalla query NON possono essere utilizzati direttamente per la costruzione della serie.

    Ad esempio, se ogni barra ha un inizio e una fine, se sottoponi una query che contiene solamente la prima informazione (ossia l'inizio) non può funzionare.

    Devi produrre una query che abbia un output compatibile con la struttura attesa dal grafico, ossia quei campi che contengono le medesime informazioni che inserisci quando agisci manualmente. In alternativa, lasci inalterata la query ma fai una scansione diretta del DataSet, partendo dal primo record fino a esaurimento dei dati, inserendoli nel grafico andando a sopperire a eventuali mancanze (ovvero i dati che inserisci manualmente).

    ziobacco ha scritto:


    mi manca quindi qualche pezzo, non capisco [...]
    Ho altre domande [...]
    insomma sono un attimo in alto mare
    Io procederei con la modalità "dividi et impera": parti da un problema, verifica i dati da specificare, prepara la query, scrivi la procedura di conversione dei dati per renderli compatibili con quelli attesi dal grafico, poi si passa alla rifinitura delle caratteristiche del grafico.

    Ciao!
  • Re: Tdbchart e gantt

    Grazie Aika,
    alla fine ho provato a non usare direttamente la query, ma piuttosto a ciclarla ed aggiungere un punto alla volta.

    tipo cosi:
    
        with dmmain.FDQryT4 do
      begin
        First;
        while not(Eof) do
        begin
          if Series3.Count>0 then
          begin
            Series3.EndValues[Series3.Count-1] :=  FieldByName('ts').AsDateTime;
          end;      	 
    Series3.AddGanttColor(FieldByName('ts').AsDateTime,FieldByName('ts').AsDateTime,3,FieldByName('num').AsString,numtocolor(FieldByName('num').AsInteger));
          Next;
        end;
      end;
    
    quindi in sostanza aggiungo il primo punto con start e end uguali, al record successivo assegno l' end = allo start attuale.

    finito il ciclo, per poter vedere la label con una etichetta al primo punto gli assegno la label.

    quello che ottengo è: manca la legenda perchè mi metterebbe ogni singolo punto e non è quello che voglio, al limite aggiugero' un pannello a mano.

    punto successivo:
    mi piacerebbe che al passaggio del mouse su ogni barretta mi uscisse un tooltip che indicasse: start,stop,valore.

    nell' esempio sopra per esempio mettendo il mouse sulla seconda barretta, quella verde, vorrei mi uscisse una tootip :

    start = 21:40
    end = 21:45
    durata = 5
    valore = 2

    ma onestamente nn so come fare
  • Re: Tdbchart e gantt

    Forse ho trovato un modo , non so se è quello piu' corretto ma fa quello che volevo ( all' incirca):
    
    procedure TForm2.DBChart1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    var
      dStart, dEnd: TDateTime;
      i, SeriesIndex: Integer;
      ValueIndex: Integer;
    begin
      DBChart1.ShowHint := False;
      try
        for i := 0 to DBChart1.SeriesCount - 1 do
        begin
          SeriesIndex := i;
          ValueIndex := DBChart1.Series[SeriesIndex].Clicked(X, Y);
          if ValueIndex <> -1 then
            Break;
        end;
    
        DBChart1.ShowHint := ValueIndex <> -1;
        if DBChart1.ShowHint then
        begin
          dStart := TGanttSeries(DBChart1.Series[SeriesIndex]).StartValues[ValueIndex];
          dEnd := TGanttSeries(DBChart1.Series[SeriesIndex]).EndValues[ValueIndex];
          DBChart1.Hint := 'Time start: ' + FormatDateTime('hh:nn:ss.zzz', dStart) + #13#10 +
                           'Time stop: ' + FormatDateTime('hh:nn:ss.zzz', dEnd) + #13#10 +
                           'Time duration: ' + FormatDateTime('nn:ss.zzz', dEnd - dStart)+#13#10+
                           'Mode: '+ TGanttSeries(DBChart1.Series[SeriesIndex]).Labels[ValueIndex];
        end;
      except
      end;
    end;
    
  • Re: Tdbchart e gantt

    Diciamo che sono arrivato ad ottenre circa quello che volevo, come da immagine:
    1.PNG
    1.PNG

    il grafico gantt viene quindi creato ciclando la query.
    mentre il grafico di sotto è ottenuto tramite altre 3 query, senza scrivere codice.

    ora, le 3 query hanno tutte un intervallo temporale, quello che vorrei ottenre è cmq un grafico in realtime, con un intervallo temporale dell'ultima ora.

    quello che pensavo è mettere un timer ogni 5 secondi per esempio che refresha gli oggetti query passandogli l intervallo temporale now(); now-60 minuti.

    Solo che cosi facendo, siccome ho molti dati a database, per caricare il tutto ci mette qualche secondo, in cui in sostanza è tutto bloccato.

    Soluzione?
    pensavo di mettere le select in un thread, oppure non ce un modo per caricare solo i dati nuovi?, nello specifico sarebbero solo i nuovi 5 secondi del timer.per la select non ce problema, ma immagino che il grafico a quel punto mi faccia vedere solo quei 5 secondi e non i punti prima.

    qualche consiglio?
    se aggiungessi a mano tutti i punti invece che darli in pasto al dbchart immagino si possa, ma a sto punto mi domando cosa mi serva il DB chart ... speravo ci fosse un modo per farlo senza dover ciclare e aggiungere a mano i dati, anche perchè credo che comuque se lo fa lui forse è piu veloce rispetto a un ciclo magari di 8000 record.
  • Re: Tdbchart e gantt

    Alla fine ho creato un asse per ogni serie che mi serve,cosi posso definire poi i vari massimi e minimi di scala ecc.

    quello che ottengo è
    skifez.PNG
    skifez.PNG

    come faccio ad evitare che la varie label degli assi si sovrappongano?

    ho provato a distanziarle con
    Axes.LabelsSize:=20;

    o anche con
    axea.LabelWidth(20);

    ma non funziona, sono assi custom creati a runtime, mi viene il dubbio che funzioni solo sul componente tchart PRO, io ho il base, infatti a design time non mi fa neppure creare assi custom.

    ma esiste un modo per non far scrivere sovrapposte le label?, non ci sono proprio riuscito.
  • Re: Tdbchart e gantt

    ziobacco ha scritto:


    Alla fine ho creato un asse per ogni serie che mi serve,cosi posso definire poi i vari massimi e minimi di scala ecc.
    [...]
    ma esiste un modo per non far scrivere sovrapposte le label?, non ci sono proprio riuscito.
    Sfrutta tutti i lati del grafico che hai a disposizione. Quando sono esauriti, dubito che ci sia il modo di sfruttare lo stesso spazio per mostrare dei valori in corrispondenza del grafico che si equivalgono, e quindi richiedono l'etichetta nello stesso punto, ma senza sovrapporsi ad altre se le rendi tutte visibili.

    Infatti, se la scala è la stessa, e tu imposti una distanza/taratura basata su un intervallo generico e non sul posizionamento dei valori delle serie sul grafico, allora ti basterebbe visualizzare le label per un solo asse e non per tutti (che te ne fai degli altri se i valori sono gli stessi?).

    Ciao!
  • Re: Tdbchart e gantt

    Perdonami Alka ma non ho ben capito la tua risposta ... pero' posso dirti che comunque ho 6 serie, 3 le ho messe sugli assi di sinistra e 3 sugli assi di destra, nel caso specifico della immagine di prima la scale era circa la stessa, ma potrebbero essere 6 totalmente differenti.

    quindi per esempio sull asse di sinistra un valore 30 riferito ad una serie potrebbe accavallarsi con un valore 60.000 referito ad un altra serie.
  • Re: Tdbchart e gantt

    ziobacco ha scritto:


    pero' posso dirti che comunque ho 6 serie, 3 le ho messe sugli assi di sinistra e 3 sugli assi di destra, nel caso specifico della immagine di prima la scale era circa la stessa, ma potrebbero essere 6 totalmente differenti. [...]
    quindi per esempio sull asse di sinistra un valore 30 riferito ad una serie potrebbe accavallarsi con un valore 60.000 referito ad un altra serie.
    Che ci siano valori accavallati tra serie che hanno la legenda su assi diversi (es. una a sinistra e una a destra) ci può stare, ma non ha senso avere sul medesimo asse dei valori a confronto che appartengono a scale differenti, addirittura 3 diverse.

    In quel caso, ci sta che si sovrappongano, oppure si deve utilizzare un intervallo tra label consono per evitare sovrapposizioni.
    Non vedo altre soluzioni.
  • Re: Tdbchart e gantt

    Passo oltre

    ho un problema piu serio ma direi concettuale piu che di programmazione, ci provo:
    Allora ho una macchina a stati che mi invia uno stato che ha dei valori tra x e y, diciamo da 1 a 5, alla ricezione di questo valore di stato memorizza questo stato in una tabella a database.

    Il gantt in questione non fa altro che fare una select di questi valori e visualizzarli sulla serie gantt dando ad ogni stato un colore.

    per esempio 1=giallo;
    2=rosso
    3=verde ecc

    io devo visualizzare il grafico delle ultime due ore, dovrebbe essere una sorta di grafico in real time, quindi ogni 5 secondi lo refresho, da qui nasce anche il discorso delle query per trovare l ultimo record inserito prima di una data.

    perché se lo stato non cambia nelle ultime due ore la mia select non tira fuori nessun dato quindi non visualizzo nulla, dovrei andare a prendere l ultimo stato inserito, perche se da quel momento in poi non ho ricevuto nulla vuol dire che si trova ancora in quello stato.

    Visto che di fatto nn posso optare per quella soluzione perche non é che posso aspettare la open di una query 30 secondi su un grafico che dovrebbe essere in real time....

    avete qualche idea?
  • Re: Tdbchart e gantt

    ziobacco ha scritto:


    perché se lo stato non cambia nelle ultime due ore la mia select non tira fuori nessun dato quindi non visualizzo nulla, dovrei andare a prendere l ultimo stato inserito, perche se da quel momento in poi non ho ricevuto nulla vuol dire che si trova ancora in quello stato.
    Non ti basterebbe memorizzarti il valore dell'ultimo stato e conservarlo fino a quando non ne arrivano di nuovi, tenendo sempre l'ultimo in memoria?
  • Re: Tdbchart e gantt

    Ci avevo pensato, ma purtroppo non mi basta,perche ho piu di una macchina, e al click sul disegnino della macchina mi aggiorna il grafico relativo a quella macchina, quindi rieseguendo la query filtrando i dati per quella macchina.

    diciamo che accendo il software alle 8, il timeframe è quindi dalle 6 alle 8.
    mettiamo che alle 8.10 arrivi un valore, per esmpio 1, viene memorizzato in tabella e a quel punto io lo vedo, e lo memorizzo come ultimo valore arrivato. percui io dalle 8.10 in poi "allungo" la fine del grafico gantt fino a now(), perfetto.

    quando quel punto esce dal grafico, percui alle 11.11 è fuori dal timeframe, quindi la mia query non ritorna nessun valore, ma io ho l ultimo valore memorizzato lo prendo e riempio il gant per tutto il timeframe delle "nuove" 2 ore, sembra funzionare.


    ma se alle 8.20 mi arriva un altro valore, ad esempio 2, alle 8.30 un altro, ad esempio 3, l ultimo valore diventa 3.

    quando il punto 2 scifta fuori dal grafico, a quel punto io mi perdo il valore dalle 8.20 all 8.30, e non è l ultimo puunto (il 3), ma dovrei recuperare il 2 e inserirlo dalle 8.21 fino all 8.30, dove poi inizia il 3.

    se non dovessi cliccare su un altra macchina e stare sempre sulla pagina del grafico potrebbe anche funzionare perche non cancella il grafico ricaricando i valori, ma dato che se esco dalla pagina o se clicco su un altra macchine e poi ritorno su quella, riesegue la select ricreando il grafico, quindi mi perdo di fatto il punto 2.

    non so se sono riuscito a spiegarmi.
  • Re: Tdbchart e gantt

    ziobacco ha scritto:


    Ci avevo pensato, ma purtroppo non mi basta,perche ho piu di una macchina, e al click sul disegnino della macchina mi aggiorna il grafico relativo a quella macchina, quindi rieseguendo la query filtrando i dati per quella macchina.
    E chi dice che non puoi memorizzare l'ultimo valore per ciascuna macchina?
    Il linguaggio è ricco, le collezioni sono tante: liste, dizionari, ecc.
Devi accedere o registrarti per scrivere nel forum
16 risposte