TChart: x-Achse automatisch anpassen



  • In einem TChart schreibe ich Daten. In der x-Achse wird die Zeit in Minuten dargestellt. Da die Datenerfassug über mehrere Tage läuft ist die Anzeige in Minuten irgendwann nicht mehr übersichtlich. Daher möchte ich, dass sich die x-Achse nach 600 Minuten in Stunden und nach 120h in Tage umstellt.
    So werden die Daten minütlich in den Chart geschrieben:

    void __fastcall TfrmMain::btnStartProzessClick(TObject *Sender)
    {
        timDatenerfassung->Interval = StrToInt(txtMessintervall->Text) * 60000; //Timerintervall in Minuten
        timDatenerfassung->Enabled = true; //Timer starten
        index = 0;
    }
    
    void __fastcall TfrmMain::timDatenerfassungTimer(TObject *Sender)
    {
        int xValue = txtMessintervall->Text.ToInt() * index;   
        Series1->AddXY(xValue, messwert, "", clTeeColor);
        index++;
    }
    

    Wie kann ich die x-Achse automatisch anpassen lassen?



  • Es gibt eine Event OnGetAxisLabel der Klasse TChart , da kannst du durch Zuweisung an einen String die Beschriftung der Achse selbst setzen.



  • Hallo,

    Man könnte auch das Format der X-Werte auf DateTime umstellen (TChartSeries::XValues::DateTime). Dann kann man mit Hilfe von TChartAxis::DateTimeFormat jeweils das Darstellungsformat der Axe den Gegebenheiten anpassen (mm für Minuten, hh für Stunden etc.).



  • wie macht man das? Komme bis hier hin:

    Chart1->Series->XValues
    

    Leider funktioniert meine Borland-Hilfe nicht.



  • Hallo,

    Das steht auch nicht in der Borland Hilfe sondern in der von TChart
    Umschalten auf DateTime Format

    Chart1->Series->XValues->DateTime = true
    

    Setzen Axen-Format auf zweistellige Minuten einstellen.

    Chart1->BottomAxis->DateTimeFormat = "mm";
    // Major steps auf eine Minute stellen
    Chart1->BottomAxis->Increment = DateTimeStep[ dtOneMinute];
    

    Das DateTimeStep Array enthält Daten für folgende enums

    dtOneMicroSecond, dtOneMillisecond, dtOneSecond, dtFiveSeconds, dtTenSeconds, dtFifteenSeconds, dtThirtySeconds, dtOneMinute, dtFiveMinutes, dtTenMinutes, dtFifteenMinutes, dtThirtyMinutes, dtOneHour, dtTwoHours, dtSixHours, dtTwelveHours, dtOneDay, dtTwoDays, dtThreeDays, dtOneWeek, dtHalfMonth, dtOneMonth, dtTwoMonths, dtThreeMonths, dtFourMonths, dtSixMonths, dtOneYear, dtNone



  • Chart1->Series->XValues->DateTime = true;
    

    in dieser Zeile kommt flg. Fehler:

    [C++ Fehler] unitMain.cpp(33): E2193 Zu wenige Parameter im Aufruf von '_fastcall TCustomAxisPanel::GetSeries(int)'
    

    Die Hilfe wird mir nun angezeigt. Leider stehen dort keine Beispiele, wie man DateTime nun setzt.



  • Series ist ja auch ein Array. Du muss also folgendes angeben

    Chart1->Series[0]->XValues->DateTime = true;
    


  • alles klar.

    Zum Testen habe ich mir ein kleines Testprogramm geschrieben:

    TDateTime zeit = 0;
    int index = 0;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
       : TForm(Owner)
    {
       Chart1->Series[0]->XValues->DateTime = true;
       Chart1->BottomAxis->DateTimeFormat = "ss";
       Chart1->BottomAxis->Increment = DateTimeStep[dtOneSecond];
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::timDatenerfassungTimer(TObject *Sender)
    {
       Series1->AddXY(zeit, rand(), "", clTeeColor);
       zeit += double(1.0/SecsPerDay);
       Label1->Caption = zeit;
       index++;
    
       if (index > 59)
          Chart1->BottomAxis->DateTimeFormat = "mm:ss";
    
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::btnStartClick(TObject *Sender)
    {
       timDatenerfassung->Enabled = true;
       zeit = 0;
       index = 0;
    }
    

    Das Intervall des Timers steht auf 1000 (= 1 Sekunde). Damit wird jede Sekunde inkrementiert. Nun wollte ich eigentlich, dass er nach 600 Sekunden auf Minuten umstellt und dann irgendwann auf Stunden usw. Nach 59 Sekunden kommt nun aber 00. Ist ja auch klar bei TDateTime. Also kann er ja dann die Minuten davorschreiben und nach 10 Minuten die Sekunden weglassen. bei den Stunden dann dasselbe. Ich versteh aber nicht warum er nach 60 Sekunden dann 12:00, 12:01, 12:02 usw schreibt. Die Zeit habe ich doch auf 0 gesetzt.



  • Hallo,

    Da hatte ich dir ein falsches Format vorgegeben.
    mm bedeutet Monat und nicht Minute. nn ist Minute. Siehe auch bei TDateTime::FormatString



  • wenn ich

    Chart1->BottomAxis->DateTimeFormat = "dd:hh:mm:ss";
    

    verwende steht in der x-Achse 30:00:00:00. Wieso das? Der x-Wert ist doch kleiner als 1.

    Edit: Grad selbst draufgekommen. Da ich einer Variablen vom Typ TDateTIme am Anfang 0 zuweise steht das ja für das Datum 30.12.1899. Daher die 30.

    So kann ich TDateTime dann für meinen Fall nicht nehmen, da ich die Dauer eines Prozesses anzeigen will in Anzahl der Minuten, Stunden, Tage.



  • Habe es nun mit dem Vorschlag von DocShoe mit dem Event GetOnAxisLabel probiert. Leider ist das in der Borland-Hilfe schlecht dokumentiert bzw es gibt auch kein Beispiel. Hier mal mein Versuch:

    void __fastcall TForm1::Chart1GetAxisLabel(TChartAxis *Sender,
          TChartSeries *Series, int ValueIndex, AnsiString &LabelText)
    {
       int time;
       if (Sender == Chart1->BottomAxis)
       {
          time = StrToInt(LabelText);
          if (ValueIndex > 600) {
             LabelText=IntToStr(time/60);
          }
       }
    }
    

    Nach 600 Sekunden soll in Stunden umgestellt werden. Funktioniert so leider nicht.



  • Dann machste was falsch...

    Gewöhn dir bitte an, detaillierte Fehlerbeschreibungen abzugeben, die Aussage "funktioniert so leider nicht" ist da keineswegs hilfreich.



  • Eine Fehlermeldung gibt es nicht, aber der Graph wird nicht wie gewünscht in das Chart gezeichnet. Auf jeden Fall kann ich so die Labels der x-Werte nicht ändern. Die Werte der x-Achse steigen nur (Inkrement 1). Ab einen x-Wert von 600 (Minuten) sollen alle x-Werte durch 60 geteilt werden (Darstellung in Stunden). Wie wende ich die Methode GetAxisLabel dabei an? Hier der Code:

    int zeit = 0;
    void __fastcall TForm1::timDatenerfassungTimer(TObject *Sender)
    {
       Series1->AddXY(zeit, rand(), "", clTeeColor);
       zeit++;
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::btnStartClick(TObject *Sender)
    {
       timDatenerfassung->Enabled = true;
       zeit = 0;
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Chart1GetAxisLabel(TChartAxis *Sender,
          TChartSeries *Series, int ValueIndex, AnsiString &LabelText)
    {
    
       if (Sender == Chart1->BottomAxis) //laut Hilfe von TeeChart
       {
          //??? 
          // hier muss ja dann der x-Wert geprüft werden (if xWert >= 600) {}
          //???
       }
    }
    

    Wie spreche ich den aktuellen x-Werte an und ändere die vorherigen?
    Leider ist die Hilfe von TChart sehr schlecht erläutert bzw es gibt kein passendes Beispiel dazu. Auch die Suche im Forum und im Netz brachte mich nicht weiter zu der Funktion GetAxisLabel. So wie ich das sehe, wird sie jedes Mal wenn ein Wert in den Chart geschrieben wird aufgerufen.



  • weiss jemand die Antwort auf die Frage?


Anmelden zum Antworten