Admin |
Отправлено: 16.04.2004, 13:23 |
|
Владимир
Группа: Администратор
Сообщений: 1190
|
Есть TChart в нем несколько Series (графиков)
Нужно чтобы рядом с каждым графиком выводилась
некая информация (строка текста) :
или справа(как на приложенном графике — "Гр 1" и "Гр 2"),
или прямо рядом с линией графика.
Легенда не годится, так как график будет печататься на ч/б принтере,
и цвета не будет — а нужно конкретное обозначение -
какой график для чего.
Или если-бы можно было-бы как-то нарисовать
для Series->Marks->Label не для всех точек серии,
а только для одной(любой) из точек и вывести там
некую информацию.
Ваши предложения...
Присоединить изображение
|
|
Admin |
Отправлено: 16.04.2004, 14:39 |
|
Владимир
Группа: Администратор
Сообщений: 1190
|
Нашел решение.
в .h
CODE |
private: // User declarations
void __fastcall SeriesGetMarkText(TChartSeries *Sender,
int ValueIndex, AnsiString &MarkText);
|
в .cpp
CODE |
//---------------------------------------------------------------------------
TLineSeries *Ls = new TLineSeries(this);
Ls->ParentChart = Chart;
Ls->Marks->Visible = true;
Ls->OnGetMarkText = SeriesGetMarkText;
Ls->Marks->ArrowLength = 16;
...
void __fastcall TForm1::SeriesGetMarkText(TChartSeries *Sender,
int ValueIndex, AnsiString &MarkText)
{
if(ValueIndex != nPoz) MarkText = "";
else MarkText = ((TLineSeries*)Sender)->Title;
}
//---------------------------------------------------------------------------
|
В результате выводится 1 Mark в указанной nPoz позиции
(нужная мне строка, в данном случае название серии Title)
Отредактировано Admin — 16/04/2004, 16:51
|
|
Gedeon |
Отправлено: 16.04.2004, 15:23 |
|
Ветеран
Группа: Модератор
Сообщений: 1742
|
Да просто все однако бывает, а я тут уже нагородил вывод текста на канве, с высотой по У в зависимости от последнего значения Series, а Х всегда постоянный. Геморройно тем, что после любой перерисовки нужно перебирать серии и рисовать, плюс расчет изменения масштаба при изменении размеров.
|
|
Admin |
Отправлено: 16.04.2004, 15:45 |
|
Владимир
Группа: Администратор
Сообщений: 1190
|
К сожалению и у этого решения есть минусы.
Почему только это так плохо реализовано -
нужно было к свойству Title у Series добавить
возможность вывода этого Title в указанном месте.
А то если несколько графиков — и как их различать
прикажете (особенно в распечатке на ч/б принтере ?)
ToGedeon:
Если не сложно, приведите код вашего решения.
|
|
Gedeon |
Отправлено: 19.04.2004, 08:44 |
|
Ветеран
Группа: Модератор
Сообщений: 1742
|
В пятницу подумал проблема решена и не сохранил исходник, за сегодня накидаю, выложу.
|
|
Gedeon |
Отправлено: 19.04.2004, 15:33 |
|
Ветеран
Группа: Модератор
Сообщений: 1742
|
Вот накидал:
CODE |
void __fastcall TForm1::Button1Click(TObject *Sender)
{ // это так кошки, на которых тренироваться
TFastLineSeries * S = new TFastLineSeries(this);
TFastLineSeries * S1 = new TFastLineSeries(this);
TFastLineSeries * S2 = new TFastLineSeries(this);
for(int i=0; i<10;i++){
S->AddXY(i,i,"",clRed);
S1->AddXY(i,i+1,"",clRed);
S2->AddXY(i,i+2,"",clRed);
}
Chart1->AddSeries(S);
Chart1->AddSeries(S1);
Chart1->AddSeries(S2);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Chart1AfterDraw(TObject *Sender)
{ // собственно само рисование (от кошек не зависит)
int SeriesCount = Chart1->SeriesCount();
if(SeriesCount==0) return;
double MaxAxisValue = Chart1->Series[0]->MaxYValue();
double MinAxisValue = Chart1->Series[0]->MinYValue();
int X = Chart1->Width-60; /* 60 — расстояние от правого края чарта до графика — расстояние от графика до текста*/
for(int i=0; i<SeriesCount; i++){
if(MaxAxisValue<Chart1->Series[i]->MaxYValue()){
MaxAxisValue=Chart1->Series[i]->MaxYValue(); /*максимальное значение всех серий*/
}
if(MinAxisValue>Chart1->Series[i]->MinYValue()){
MinAxisValue=Chart1->Series[i]->MinYValue(); /*минимальное значение всех серий*/
}
}
double AxisHeight = MaxAxisValue — MinAxisValue; /* высота оси*/
for(int i=0; i<SeriesCount; i++){
int Y;
Y = Chart1->Height — Chart1->Height*
(Chart1->Series[i]->YValues->Value[Chart1->Series[i]->XValues->Count()-1]
/AxisHeight) +20; /* 20 — расстояние от верха чарта до графика — половина высоты текста*/
Chart1->Canvas->TextOutA(X,Y,("Test" + IntToStr(i)));
}
}
//---------------------------------------------------------------------------
|
Изображение того, что удалось получить пытаюсь приложить, хрен пойму как это делать. Это все действительно конечно если ось У линейная, иначе надо пересматривать алгоритм расчета массштаба, да и все это в таком виде подходит только под конкретный график (из-за чисел описанных в коментариях, но если порыть свойства можно эти значения и рассчитать). Это конечно далекий от совершенства пример, так просто идея, тут наверняка можно чего-нибудь соптимизировать.
Отредактировано Gedeon — 19/04/2004, 16:39
Присоединить изображение
|
|
Admin |
Отправлено: 19.04.2004, 16:36 |
|
Владимир
Группа: Администратор
Сообщений: 1190
|
Большое спасибо, то что и было нужно
Только чуть подправил:
CODE |
//---------------------------------------------------------------------------
void __fastcall TForm1::Chart1AfterDraw(TObject *Sender)
{
int SeriesCount = Chart1->SeriesCount();
if(SeriesCount==0) return;
for(int i=0; i<SeriesCount; i++){
int LastValueIndex = Chart1->Series[i]->LastValueIndex;
int X = Chart1->Series[i]->CalcXPos(LastValueIndex);
int Y = Chart1->Series[i]->CalcYPos(LastValueIndex);
Chart1->Canvas->TextOutA(X,Y-10,("Test" + IntToStr(i)));
}
}
//---------------------------------------------------------------------------
|
P.S. И не забыть поставить MarginRight, чтобы надпись влезла,
типа Chart1->MarginRight = 10;
Отредактировано Admin — 19/04/2004, 17:43
|
|
Gedeon |
Отправлено: 19.04.2004, 16:45 |
|
Ветеран
Группа: Модератор
Сообщений: 1742
|
Тут вот еще что подумалось, если значения сойдутся близко в конце графика, нужно проверять разницу между У и тогда соответственно рассчитать Х, т.е. сместить второй на несколько позиций вправо.
|
|
Admin |
Отправлено: 19.04.2004, 16:54 |
|
Владимир
Группа: Администратор
Сообщений: 1190
|
Вот так получилось.
Присоединить изображение
|
|