Помощь - Поиск - Пользователи - Календарь
Полная версия: Работа с осями в Tchart
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Делфи
AlexSCH
Численные значения по осям привязаны строго к графику, который этот компонент отображает. Размерность чисел по осям не соответсвует реальным параметрам. То есть, отображается в 1 компоненте TChart 8 графиков, после построения все они находятся в определенных переделах по значениям, в одной системе координат. Но каждый из графиков несет свою информацию, причем 1 график это, например, Вольты, второй - милиАмперы, возможно ли поменять шкалу по оси ординат в компоненте TChart, не меняя при этом изображение графиков? То есть поменять абстрактыне числа после построения на реальные вольты или амперы и т.д.
klem4
ИМХО не стоит в одной системе координат размесщать среднемесячную температуру северных райнов Иднии и среднюю посещаемость форума "Все о Паскале" smile.gif

Зачем смешивать красное и мокрое ? Может стоит разные графики (для которых требуются разные размерности по осям) рисовать на разных ТЧартах ? Или в разное время ? По моему это более чем логично. Ну или я чего-то не понял.
AlexSCH
хорошо, а можно ли вообще менять размерность по осям? например, если у меня 100 значений какого-то параметра, при выведении на TСhart по оси Х будут цифры от 0 до 100, а в реальности каждое значение это
0.1 сек (выборка), то есть мне нужно чтобы шкала выглядела так от 0 до 10 сек, причем графическая информация не должна меняться.
volvo
AlexSCH, в дистрибутиве Дельфи (в 6-ой версии, по крайней мере) есть пример использования TeeChart. Так вот в том примере по-моему Features -> Custom Axis Labeling как раз показывает, как менять надписи на осях. Сам график при этом не меняется...
klem4
Chart1.BottomAxis.Minimum := 0;
Chart1.BottomAxis.Maximum := 1;
Chart1.BottomAxis.Increment := 0.1;


Длч нижней оси :

- максимальное значение = 1
- минимальное значение = 0
- шаг = 0.1

Навеняка все это можно менять и с помощью вкладки Scales.

Все это мне стало ясно, когда я побывал тут.

Зайди посмотри, там есть таблица свойств космонента TChart, и картинки есть :D
AlexSCH
Цитата
Код
Chart1.BottomAxis.Minimum := 0;

  Chart1.BottomAxis.Maximum := 1;

  Chart1.BottomAxis.Increment := 0.1;


эти команды просто меняют масштаб и шаг, и все (то есть график меняется). А мне нужно заменить цифры абстрактные (например 0....100) на реальные (коэффициенты пересчета есть) чтобы шкала оси выглядела не 0...100, а, например, 0...10, и график не должен меняться.

2Volvo пытался разобратся с компонентом AxiLabel что в демонстрациях, так и не понял как можно заменить, например цифру 100 на 0.1 и чтобы график не менялся. Привожу текст этого компонента, может кто-то из вас разберется.....
Код

{******************************************}
{    TeeChart. TChart Component            }
{ Copyright (c) 1995-2001 by David Berneda }
{    All Rights Reserved                   }
{******************************************}
unit uaxislab;

interface

{ This Sample Project shows how to set the Axis Labels at specific Axis
  positions.
  The key is the Chart.OnGetNextAxisLabel event.
  This event is called continuosly for each Axis Label until user decides
  to stop.
  At each call, you can specify the exact Axis value where a Label must be
  drawn.

  In this example, this event is used to set the BottomAxis labels to the
  first (1) day in month:   1/1/96,  2/1/96, 3/1/96..... 12/1/96

  This don't needs necessarily to be datetime values.
  You can also set the Axis Labels in non-datetime axis.

  WARNING:
    Remember to set the Stop boolean variable to TRUE when no more labels are
    needed.
    Remember also that using this event will NOT calculate Label used space or
    any Font size adjustment.
    TeeChart Axis will draw all labels you specify.
}
uses
  SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  Forms, Dialogs, Chart, Series, ExtCtrls, StdCtrls, Teengine, Buttons,
  TeeProcs;

type
  TAxisLabelsForm = class(TForm)
    Chart1: TChart;
    LineSeries1: TLineSeries;
    Panel1: TPanel;
    RadioGroup1: TRadioGroup;
    PointSeries1: TPointSeries;
    BitBtn3: TBitBtn;
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
    procedure RadioGroup1Click(Sender: TObject);
    procedure Chart1GetNextAxisLabel(Sender: TChartAxis;
      LabelIndex: Longint; var LabelValue: Double; var Stop: Boolean);
  private
    { Private declarations }
  public
    { Public declarations }
    DefaultLabels:Boolean;
  end;

implementation

{$R *.dfm}

procedure TAxisLabelsForm.FormCreate(Sender: TObject);
var t:Longint;
begin
  DefaultLabels:=False;  { <-- boolean variable to show or not the demo }

  LineSeries1.Clear;
  PointSeries1.Clear;
  for t:=1 to 100 do
  Begin
    LineSeries1.AddXY( Date+t, 200+Random(700),'',clTeeColor);  { <-- some random points }
    PointSeries1.AddXY( Date+t, 200+Random(700),'',clTeeColor);
  end;
end;

procedure TAxisLabelsForm.RadioGroup1Click(Sender: TObject);
begin
{ Choose between default and custom labeling. }
  DefaultLabels:=RadioGroup1.ItemIndex=0;
  Chart1.Repaint;  { <-- repaint chart to see changes }
end;

procedure TAxisLabelsForm.Chart1GetNextAxisLabel(Sender: TChartAxis;
  LabelIndex: Longint; var LabelValue: Double; var Stop: Boolean);

var year,month,day:Word;
begin
  if not DefaultLabels then
  Begin
    if Sender=Chart1.BottomAxis then
    Begin
      { ***************************** }
      { WARNING:

          Setting this axis increment:

          Chart1.BottomAxis.Increment := DateTimeStep[ dtOneMonth ];

          and...

          Chart1.BottomAxis.ExactDateTime := True;

          Eliminates the need for the following code.
      }
      { ***************************** }

     { LabelValue has the "candidate" value where the Axis label will be painted. }
      DecodeDate(LabelValue,year,month,day);
      { we force that value to be the first day in month }
      Day:=1;
      Month:=Month+1;
      if Month>12 then
      Begin
        Month:=1;
        Year:=Year+1;
      end;
      { Then we set the preferred Label value }
      LabelValue:=EncodeDate(year,month,day);

    end
    else
    if Sender=Chart1.LeftAxis then
    Begin
      { In this example, we want the Vertical Left Axis to show
        labels only for positive values, starting at zero and
        with 250 label increment.
      }
      if LabelValue>=250 then LabelValue:=LabelValue+250
                         else LabelValue:=250;
    End;
    { we want more labels !! }
    Stop:=False;
  end;
end;


end.


Зарнее спасибо.
volvo
Ну, например, вот так:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Spin, OleCtnrs, TeEngine, Series, ExtCtrls, TeeProcs,
Chart;

type
TForm1 = class(TForm)
Chart1: TChart;

Button1: TButton;
LineSeries1: TLineSeries;
PointSeries1: TPointSeries;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Chart1GetAxisLabel(Sender: TChartAxis; Series: TChartSeries;
ValueIndex: Integer; var LabelText: String);
private
{ Private declarations }
public
{ Public declarations }
DefaultLabels: Boolean;
end;

var
Form1: TForm1;

implementation

{$R *.dfm}


procedure TForm1.Button1Click(Sender: TObject);
begin
defaultLabels := not DefaultLabels;
Chart1.Repaint;
end;

procedure TForm1.FormCreate(Sender: TObject);
var t: LongInt;
begin
DefaultLabels:=True;

LineSeries1.Clear;
PointSeries1.Clear;
for t:=1 to 20 do
Begin
LineSeries1.AddXY( Date+t, 200+Random(700),'',clTeeColor); { <-- some random points }
PointSeries1.AddXY( Date+t, 200+Random(700),'',clTeeColor);
end;
end;

procedure TForm1.Chart1GetAxisLabel(Sender: TChartAxis;
Series: TChartSeries; ValueIndex: Integer; var LabelText: String);
begin
if not defaultlabels then

{ А вот из-за чего, собственно, это и делалось: }
if sender = chart1.LeftAxis then begin
labeltext := floattostr(strtofloat(LabelText) / 1000);
end;
end;

end.


Обрати внимание, я не использовал OnGetNextAxisLabel, а использовал OnGetAxisLabel... wink.gif

В списке Uses могут быть лишние модули, не пугайся, я просто добавлял этот код в другой проект...
AlexSCH
2Volvo
Попробовал твой вариант, не заработало, сколько я ни пытался отследить пошагово, но ниразу указатель не попадал в процедуру TForm1.Chart1GetAxisLabel, то есть не происходило выполнение процедуры, на кнопку жмешь, меняется состояние DefaultLabels и все, или я уже совсем запутался, просвети пожалуйста?
Мне просто интересно, как запустить вот эту процедуру, где меняются значения по осям?
volvo
Присоединяю полностью проект (жми на кнопку и смотри на левую ось):

Если надо - говори, присоединю и EXE-шник...

Нажмите для просмотра прикрепленного файла

Брекпойнт поставь внутрь процедуры Chart1GetAxisLabel, туда где он стоит у меня. И запусти через F9 ...
AlexSCH
Получается что эта процедура выполняется постоянно?
volvo
Цитата(Delphi Help)
OnGetAxisLabel Event

Declaration
property OnGetAxisLabel : TAxisOnGetLabel
Description
An Event is triggered for each Axis Label painted. There are two different uses for OnGetAxisLabel:
<...>

Таким образом ответ на твой вопрос - "нет", потому, что эта процедура выполняется перед каждой отрисовкой метки оси (кстати, как раз удобно для случая, если тебе понадобится подменить эту метку), но не постоянно. Попробуй убрать Chart1.Repaint из обработки нажатия на кнопку, и ты в этом убедишься.
AlexSCH
Вообще чудеса....... blink.gif
В своем проекту не получается.
К твоему проекту добавил еще один TChart, прописал все то же самое для него, в результате созданный тобой работает, а на моем ось не меняется, в чем загвоздка?

Архив проекта я прикрепил.
volvo
Нет... smile.gif Так не пойдет... OnGetAxisLabel - событие, а не простая процедура... Поэтому если ты внутри метода Chart1GetAxisLabel пишешь вот это условие:

    if sender = chart2.LeftAxis then begin
labeltext := floattostr(strtofloat(LabelText) / 1000);
end;
, то эта попытка изначально обречена на провал. Нужно обрабатывать событие OnGetAxisLabel для второго чарта...
AlexSCH
вроде для второго чарта написал отдельную обработку события, но все равно не работает.......((((
volvo
Угу... Написать-то ты написал, только вероятно ВРУЧНУЮ... А вот Дельфи страшно не любит, когда программист лезет в определение класса ДО public и private... Это - территория Дельфи... Так что удаляй то, что добавил сам, в Object Inspector-е для второго чарта выбирай нужное событие и потом его корректируй, и только тогда о нем будет известно программе...

Или просто (ничего не удаляя) зайди в Object Inspector и для второго чарта выбери процедуру обработки события из списка...

Сейчас программа ничего не знает о том, что ты обработку этого события добавил...
AlexSCH
Огромное тебе спасибо Volvo, заработало так как надо. good.gif


кстати как быть с BottomAxis, если значение больше 999, у меня например график по оси х заканчивается цифрами 2146, по нажатию на кнопку выскакивает 2 146 is not a valid floating point...., я так понял, что значение возвращается с пробелом между 2 и 146, поэтому она (программа) не понимает этого значения ???
volvo
Удалить разделитель тысяч, и потом работать со строкой:

вместо
      labeltext := floattostr(strtofloat(LabelText) / 1000);


делай что-то вроде:
      labeltext := floattostr(strtofloat(

{ Это как раз уберет из оригинального LabelText разделитель тысяч }
stringreplace(LabelText, ThousandSeparator, '', [rfreplaceall])

) / 1000);
AlexSCH
Еще раз спасибо огромное за помощь.
AlexSCH
Еще вопрос, как присвоить содержимое переменной типа String названию оси.
Я делал так:
Код
gerc:=gerc+(help[i]);
i:=i+1;
Chart1.BottomAxis.Title:=gerc;

Но выдает ошибку про несовместимость форматов TCharAxisTitile и String, какой космандой можно перевести string в этот TCharAxisTitile ?
volvo
Chart1.BottomAxis.Title.Caption := gerc;
AlexSCH
В ходе выполнения программы я даю названия осям, при повторной загрузке файла с графической информацией, при отображении на его осях появляются новые названия, а также остаются старые(от прошлой графической информации), как от этого избавится? может быть 2 раза перестраивать график, 1 раз без названий (загнать в область названий пустоту), 2 раз уже с новыми названиями. Я делал так, но ничего не получилось, все равно остаются старые названия:
Код

Chart1.LeftAxis.Title.Caption:='';
Chart1.Repaint;
Chart1.LeftAxis.Title.Caption:=Ch1;
defaultLabels := not defaultLabels;
Chart1.Repaint;

volvo
Ну, это смотря как ты "повторно загружаешь файл с графической информацией". Код, при котором не происходит корректного изменения Axis.Title.Caption - в студию...
AlexSCH
Думал, думал как же это корректно выложить...... пришел к выводу что приклепу весь свой проект, в архиве с проектом есть файл '10', при запуске проги его и нужно открывать. Попробуй 2 раза его открыть, сразу добавляется название в ось Y (появляется лишняя буква В), а ось Х почему-то увеличивается в 2 раза..........
p.s. Файл PRB.EXE также нужен для корректной работы (в смысле не спеши его стирать smile.gif ).

2Volvo извините за бардак в проекте.............. smile.gif
volvo
По поводу
Цитата(AlexSCH @ 19.08.2006 16:23)
ось Х почему-то увеличивается в 2 раза..........

Очень просто... Ты делаешь
Chart1.Series[0].AddXY(t, strtoint('$'+Mat[j]));
, а кто при входе в процедуру
procedure TForm1.N4Click(Sender: TObject);
begin
If OpenDialog1.Execute
then begin
t := 0; { <-- Здесь !!! }
...
будет T сбрасывать? Оно же накапливается, и при третьей загрузке длина оси X утроится по сравнению с первой, если T не обнулить smile.gif

Теперь про ось Y... Я не добрался, честно говоря, до причины такого поведения Axis.Title.Caption, но одно выяснил совершенно точно: у тебя здесь:
          Chart1.LeftAxis.Title.Caption:='';
Chart1.Repaint;
Chart1.LeftAxis.Title.Caption:=Ch1; { <-- !!! }

в Ch1 хранится неверное значение. То есть, прибавляется B... Проблема, скорее всего, схожая, где-то не присвоил Ch := '';

Кстати, если этот проект писать как положено, используя процедуры/функции/Case, то от почти 2000 строк, что есть сейчас останется в худшем случае 400. Как думаешь, какую программу легче сопровождать? wink.gif
AlexSCH
Спасибо, разобрался, заработало smile.gif
AlexSCH
У меня еще вопрос.
Как можно поменять масштаб дополнительной оси.
Дополнительную ось я создавал так
Код

procedure TForm1.Series1AfterDrawValues(Sender: TObject);
var posaxis:longint;
begin
  With Chart1 do
  begin
    { Calculate axis position and draw... }
    PosAxis:=ChartRect.Left+Trunc(ChartWidth*YPercent/1000.0);
    LeftAxis.CustomDraw(posaxis-5,posaxis-5,posaxis+0,true);
  end;
end;

Получилось то что на вложенной картинке.
Изображение
Требуется, чтобы дополнительная ось при том же масштабе графика, была в другм масштабе единиц измерения.
То есть по типу того, как до этого сделали с главными осями Х и Y.
Как это сделать?
volvo
AlexSCH, во-первых, картинку присоедини сюда (ее невозможно посмотреть, сервер не отвечает), а во-вторых, если даешь код, так давай так, чтобы было понятно, что чему равняется...

YPercent это что такое и чему равно, например?
AlexSCH
Вот архив, с программой.
YPercent это из демо TeeChart к делфе, где оси кординат могут перемещатся, с помошью таймера, я таймер отключил, просто переменная осталась.
klem4
AlexSCH, а где Unit2 ?

кмх ... Попробуй использовать циклы в программе smile.gif

j:=1;
Chart1.Series[0].AddXY(t, strtoint('$'+Mat[j]));
t:=t+1;
j:=2;
Chart1.Series[0].AddXY(t, strtoint('$'+Mat[j]));
t:=t+1;
j:=3;
Chart1.Series[0].AddXY(t, strtoint('$'+Mat[j]));
t:=t+1;
j:=4;
Chart1.Series[0].AddXY(t, strtoint('$'+Mat[j]));
t:=t+1;
j:=5;
Chart1.Series[0].AddXY(t, strtoint('$'+Mat[j]));
t:=t+1;
j:=6;
Chart1.Series[0].AddXY(t, strtoint('$'+Mat[j]));
t:=t+1;
j:=7;
Chart1.Series[0].AddXY(t, strtoint('$'+Mat[j]));
t:=t+1;
j:=8;
Chart1.Series[0].AddXY(t, strtoint('$'+Mat[j]));
t:=t+1;


Такой код во первых выглядит странно, во вторых читается плохо

Ты можешь написать задание полностью ? Что-то мне подсказвыает, что этот код можно сократить в несколько раз, и обойтись без таких вещей :

t,tt,ttt,tttt,ttttt:integer;
r,zz,zs,zss,zx,uu,uu2,ww,zz1,zx1,zs1,zss1,zz2,xx,xx2,yy,yy2,yy1,
yy12,yyy,yyy2,www,www2,laxis,baxis,qaz,gerc44:real;
AlexSCH
Unit 2 добавил.
Файл с информацией в архиве под именем "10"
Согласен, код корявый. Добавление дополнительной оси происходит в самом конце кода вот этой процедурой procedure TForm1.Series1AfterDrawValues(Sender: TObject);
Цитата

ты можешь написать задание полностью

Задача программы отображать графическую информацию. Эта информация хранится в файле, например под именем "10", в поле TChart выводится несколько графиков, изначально они идут в единой системе координат, а требуется, при том же масштабе(расположении) графиков, чтобы было несколько осей Y, с различными масштабами единиц измерения.
В файле copy11 рисунок, там уже есть 2шкала, но я не знаю как поменять ее относительный масштаб
AlexSCH
Действительно никто не знает как поменять масштаб на второй оси??? или это действительно нереально??
volvo
Да ты покажи, НА ЧТО ты хочешь поменять? Как это выглядеть должно??? Телепаты кончились.

И программу подправь, а то она у тебя через раз дает ошибку обращения к TXT файлу, сколько можно ее перезапускать?
AlexSCH
Цитата
Да ты покажи, НА ЧТО ты хочешь поменять? Как это выглядеть должно??? Телепаты кончились.

Выглядеть это должно так: первая ось Y остается неизменной, а вторая должна отображать те же цифры что и первая, только разделенные на коэффициент, например 10. То есть, если левая шкала показывает 100, то правая на этом-же уровне далжна показывать 10. Коэффициент необязательно может быть целым числом.
Цитата
И программу подправь, а то она у тебя через раз дает ошибку обращения к TXT файлу, сколько можно ее перезапускать?

Задержку я поставил побольше должно помочь.
Измененный проект прилагается.
AlexSCH
Я переделал вид программного окна в графическом редакторе, должно выглядеть вот так как на приклепленном изображении, то есть вторая ось Y представлена в другом масштабе. Как добавленную ось Y перевести в другой масштаб? (код на дополнительную ось Y представлен в пердыдущих постах, проблема в том, что дополнительная ось Y по масштабу полностью соответствует начальной оси Y, а нужно чтобы их масштабы отличались)
Гость
Помогите пожалуйста с моей проблемой...
кусок кода:
....
var
cicli:integer;
a,b:double;
Matrix6, Matrix1: array of integer;
begin
setlength(Matrix6, 6);
setlength(Matrix1, 6);
Matrix6[1]:=2; Matrix6[2]:=51; Matrix6[3]:=53; Matrix6[4]:=23; Matrix6[5]:=1;
Matrix1[1]:=14; Matrix1[2]:=52; Matrix1[3]:=13; Matrix1[4]:=5; Matrix1[5]:=23;

for cicli:=1 to 5 do
begin
a:=Matrix6[cicli];
b:=Matrix1[cicli];
unit4.Form4.Chart1.SeriesList[0].AddXY(a,b,'',clRed);
end;
unit4.Form4.Chart1.LeftAxis.TitLE.Caption:='KTG';
unit4.Form4.Chart1.BottomAxis.Title.Caption:='MR';
unit4.Form4.ShowModal;
...
В общем, проблема в том, что график строится не в том порядке, в каком я ему добавляю точки, а по возрастанию оси Х...т.е. 1,2,23,51,53... а не 2,51,53,23,1. Как разрешить проблему?
Гость
Цитата(Гость @ 30.07.2007 3:49) *


...
В общем, проблема в том, что график строится не в том порядке, в каком я ему добавляю точки, а по возрастанию оси Х...т.е. 1,2,23,51,53... а не 2,51,53,23,1. Как разрешить проблему?


Копать куда-то сюда
Chart2.Series[2].XValues.Order := loNONE;
nishaknapp
Why not settling on games that is fun and at the same time your earning. Well it'll make suspense because the game is well but dude just try it and it gave me hope while pandemic is real rn. Casino Jobs and Their Roles
lexusflex
А мне вот не очень нравится работать программистом из-за того, что там много не заработаешь. Я предпочитаю зарабатывать деньги играя в онлайн казино Алмаз .Онлайн-казино Almaz — это инновационная платформа, использующая технологию искусственного интеллекта (ИИ), чтобы предложить игрокам больше возможностей для выигрыша, а также предоставить им безопасный и приятный опыт.
nehega
Круто. В интернете сейчас можно найти полезные возможности. Я вот пробовал сыграть в казино онлайн на деньги перейдя по этой ссылке, после чего вы сможете найти хорошие возможности прямо сейчас. Заработай сейчас большое количество денег прямо сейчас, а игровые автоматы на деньги прямо сейчас могут дать крутые бонусы.
jumbleruas
Я зарабатываю деньги на том, что играю в казино на рублях: mtstv.info/bet.php . Лучшие онлайн-казино на рубли — это те, которые предлагают щедрый бонус и имеют хорошую службу поддержки. Играть в таких казино можно с минимальными вложениями!
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.