Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > построение графика в реальном времени


Автор: gordmiand 21.2.2008, 23:44
1. Подскажите пожалуйста как можно построить какой-либо график на TChart-е не мгновенно, а чтобы график строился "во времени" - т.е. плавное построение графика....
2. Как сделать автоматическую плавную прокрутку по горизонтали графика TChart так, чтобы на экране всегда был виден процесс построения графика в реальном времени (см. п.1)
(подскажите программную реализацию п.1 и п.2)

Автор: jonie 22.2.2008, 01:15
1. добавляешь по точкам, давая приложению обновлять график (отдельным потоком или application->processmessage()) ..

Автор: petlyura 22.2.2008, 10:11
1) cur.x = (int) (double(dt - diap->Start) * Rect.Width() / diap->Range + Rect.left + 0.5);                  //get x-coordinate for the current time
cur.y = (int) (Rect.bottom - ((Options->Value - Options->LowValue) * Rect.Height()) / (Options->HighValue - Options->LowValue)); //get y-coordinate regard the value for the current time

Отрисовывая каждую точку cur с координатами cur.x, cur.y, необходимо производить вычисления:
Options - экземпляр какого-то класса, хранящего миним., макс. возможные значения и текущее значение.
Rect - область прорисовки.
diap - экземпляр структуры, например,
 struct TTimeRange
{
  TDateTime Start;              //начальное значение
  double Range;                 // дипазон (в сек.)
};
2) diap->Start = CurrentTime - diap->Range;
CurrentTime - текущее время.
Так в какой-то структуре хранишь значения, времена этих значений. С каждым новым значением, добавляешь его и текущее время в эту структуру (можно, все там организовать в виде некоторого стека). И для каждого значения прорисовываешь график по точкам, вычисляя координаты (1). После каждого такта прорисовки графика (к примеру, 0,5 сек, можно использовать TTimer) меняешь значение diap->Start (2), и опять перерисовываешь.
Где-то вот так!

Автор: petlyura 22.2.2008, 11:17
Я тут подумал, и решил, что лучше вот так вот

class TGraf : public TChart
{
public:
    TGraf( TForm* owner, TPoint point );
    void Draw1();  //прорисовка
    void __fastcall GetAxisLabel (TChartAxis*Sender,TChartSeries*Series, int ValueIndex,String& LabelText); //изменение оси
    int  MAXNUMBERGRAPHPOINT; //кол-во точек на графике
private:
    int CurrentPoint;  //номер текущей точки
    TDateTime CurrentDateTime;  //текущее время
    float Zn; //значение точки, лучше перевести в значение в пикселях на графике пропорционально
    bool First; //первое отображение?
    };

TGraf::TGraf( TForm* owner, TPoint point )
 : TChart(owner)
{
 Foot->Visible = false;
 AllowPanning = pmNone;
 AllowZoom=false;
 ClipPoints = true;

 Legend->Alignment = laBottom;
 Legend->Visible = false;
 // плоский график
 View3D = false;

 TabOrder = 1;
 BevelInner = bvNone;
 BevelOuter = bvNone;
 BorderStyle = bsNone;
 Title->Visible=false;
 Frame->Visible=true;
 Frame->Color = clGray;

 LeftAxis->Automatic=false;
 LeftAxis->AutomaticMaximum = false;
 LeftAxis->AutomaticMinimum = false;
 LeftAxis->Visible=true;

  BottomAxis->Labels = true;
 BottomAxis->MinorTickLength = 0;
 BottomAxis->TickOnLabelsOnly = 0;
 BottomAxis->Automatic=false;
 BottomAxis->AutomaticMaximum = false;
 BottomAxis->AutomaticMinimum = false;
 BottomAxis->RoundFirstLabel=false;
 BottomAxis->LabelStyle=talValue;
 BottomAxis->LabelsFont->Charset = DEFAULT_CHARSET;
 BottomAxis->LabelsFont->Height = -10;
 BottomAxis->LabelsFont->Style.Clear();
 BottomAxis->LabelsSize = 0;
 BottomAxis->AxisValuesFormat="######0.#";
 BottomAxis->Ticks->Color = clBlack;

 if(!MAXNUMBERGRAPHPOINT)
     MAXNUMBERGRAPHPOINT = 60; //к примеру, 60 точек

 OnGetAxisLabel = GetAxisLabel;
 }

//-----------------------------------------------------------------------------
void
TGraf::Draw1() 
{
   
CurrentDateTime = CurrentDateTime.CurrentDateTime(); //текущее время

for(int i=0; i < SeriesCount(); i++)
 {
  Series[i]->AddXY( CurrentPoint, Zn, "", (TColor)clTeeColor ); //добавляем точку
  if(Series[i]->Count() > MAXNUMBERGRAPHPOINT) // если их стало больше 60
     Series[i]->Delete(0); //то старую удаляем
  }
CurrentPoint++;  
if(First) //если отображение первой точки, то не прокручиваем
 {
   First=false;   
 }
 else BottomAxis->Scroll(1,false);  //иначе прокручиваем

}
//------------------------------------------------------------------------------
void __fastcall TGraf::GetAxisLabel(TChartAxis*Sender,TChartSeries*Series, int ValueIndex,String& LabelText)
{  //чтоб внизу под графиком время толково выводилось 
if(!Sender->Horizontal)
   return;
TDateTime d = CurrentDateTime;
CurrentDateTime = CurrentDateTime.CurrentDateTime();
d=d-(double)(CurrentPoint-StrToFloat(LabelText))*DateTimeStep[dtOneSecond];  //если раз в секунду прорисовываешь, ключевое слово dtOneSecond
TDateTime LastTime=d-(int)d;
LabelText=LastTime;
}


Автор: Siscipsak 1.9.2022, 16:28
Модератор: Сообщение скрыто.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)