Произвольные подписи на оси в AСhart
Модератор: Модераторы
- Nik
- энтузиаст
- Сообщения: 573
- Зарегистрирован: 03.02.2006 23:08:09
- Откуда: Киров
- Контактная информация:
Произвольные подписи на оси в AСhart
Использую TAchart для вывода статистических данных, привязанных к датам. С формированием самой диаграммы (BarSeries) проблем нет - там всё проще некуда. Но вот с подписями возникла проблема. Никак не могу понять, можно ли сделать произвольные подписи на оси Y (например так, как на нижнем рисунке во вложении). В идеале каждая подпись должна жёстко привязываться к "своей" линейке на диаграмме.
Кто-нибудь делал подобные вещи?
Кто-нибудь делал подобные вещи?
У вас нет необходимых прав для просмотра вложений в этом сообщении.
- dunin
- энтузиаст
- Сообщения: 634
- Зарегистрирован: 02.05.2007 13:18:11
- Откуда: Тољя††и
- Контактная информация:
Ну вот вроде что-то подобное
У диаграммы есть оси. У оси событие OnMarkToText как-то так...
У диаграммы есть оси. У оси событие OnMarkToText как-то так...
Код: Выделить всё
...
DataChart.AxisList.Axes[1].OnMarkToText...
...
procedure TFulForm.DataChartAxisList1MarkToText(var AText: String; AMark: Double);
begin
AText:= DateToStr(AMark);
end;У вас нет необходимых прав для просмотра вложений в этом сообщении.
- Nik
- энтузиаст
- Сообщения: 573
- Зарегистрирован: 03.02.2006 23:08:09
- Откуда: Киров
- Контактная информация:
dunin писал(а):Ну вот вроде что-то подобное
У диаграммы есть оси. У оси событие OnMarkToText как-то так...Код: Выделить всё
...
...
AText:= DateToStr(AMark);
Самое оно. Спасибо за наводку!
Для частного случая работы с датами можно использовать также свойство Axis.Marks.Source и компонент DateTimeIntervalChartSource,
пример см. в axisdemo, закладки "Customized marks" и "Date and time".
Конечно, OnMarkToText -- это самый общий случай, хоть обработчик и не сохраняется
пример см. в axisdemo, закладки "Customized marks" и "Date and time".
Конечно, OnMarkToText -- это самый общий случай, хоть обработчик и не сохраняется
- Nik
- энтузиаст
- Сообщения: 573
- Зарегистрирован: 03.02.2006 23:08:09
- Откуда: Киров
- Контактная информация:
DateTimeIntervalChartSource пытался приспособить, но больно он мутный - а лишний огород городить я не люблю, баги потом ловить геморнее
OnMarkToText идеально подошёл - всего пару строк кода дописать понадобилось (не считая ручного присвоения функции OnMarkToText в RunTime
)
OnMarkToText нормальный вариант, но возникают проблемы, когда шаг между подписями меньше в пикселях, чем ширина самой подписи.
В своё время, еще на очень старой реализации сделал модифицированные чарты для специфических задач. Примерно вот так (для даты):
формирование самой подписи к значению
и изменения шага для аккуратности
В современной реализации компонента как-то можно повлиять на шаг между подписями?
И что касается подписей, было бы не плохо иметь возможность двухстрочных...
Добавлено спустя 3 часа 34 минуты 22 секунды:
Нашел OverlapPolice.... Актуальность вопроса резко уменьшилась, но не отпала.
В своё время, еще на очень старой реализации сделал модифицированные чарты для специфических задач. Примерно вот так (для даты):
формирование самой подписи к значению
Код: Выделить всё
if FBottomAxis.Title.AxisType = atDateTime then begin
if (FXGraphMax-FXGraphMin) < 3600 then
DateTimeToString(MyText, 'dd.mm.yy hh:mm:ss', CalcDateTime(Marque))
else
DateTimeToString(MyText, 'dd.mm.yy hh:mm', CalcDateTime(Marque));
end;
if FBottomAxis.Title.AxisType = atDate then
DateTimeToString(MyText, 'dd.mm.yyyy', CalcDateTime(Marque));
if FBottomAxis.Title.AxisType = atTime then
DateTimeToString(MyText, 'hh:mm:ss', CalcDateTime(Marque));
if FBottomAxis.Title.AxisType = atNormal then
MyText:=Trim(FloatToStr(Marque));и изменения шага для аккуратности
Код: Выделить всё
ACanvas.Pen.Assign(FBottomAxis.Grid);
XGraphToImage(Debut+Pas, tP1);
XGraphToImage(Debut+2*Pas, tP2);
if FBottomAxis.Title.AxisType = atDateTime then
if (FXGraphMax-FXGraphMin) < 3600 then
dt := ACanvas.TextWidth('00.00.00 00:00:00')
else
dt := ACanvas.TextWidth('00.00.00 00:00');
if FBottomAxis.Title.AxisType = atDate then
dt := ACanvas.TextWidth('00.00.00');
if FBottomAxis.Title.AxisType = atTime then
dt := ACanvas.TextWidth('00:00:00');
if FBottomAxis.Title.AxisType <> atNormal then
if dt > (tP2-tP1)*0.8 then
while dt > (tP2-tP1)*0.8 do begin
Pas := Pas*1.5;
XGraphToImage(Debut+Pas, tP1);
XGraphToImage(Debut+2*Pas, tP2);
end;
Marque:=Debut;В современной реализации компонента как-то можно повлиять на шаг между подписями?
И что касается подписей, было бы не плохо иметь возможность двухстрочных...
Добавлено спустя 3 часа 34 минуты 22 секунды:
Нашел OverlapPolice.... Актуальность вопроса резко уменьшилась, но не отпала.
VAshot писал(а):В современной реализации компонента как-то можно повлиять на шаг между подписями?
Напрямую влиять на шаг в пикселях нельзя, хотя мысль, конечно, правильная.
Надо подумать над интерфейсом и реализацией, если есть предложения -- welcome.
Можно произвольно привязать метки к значениям координаты (в мировой системе)
с помощью свойства Source.
Можно воспользоваться TDateTimeIntervalChartSource, который автоматически
подбирает шаг изменения даты в соответствии с текущим масштабом, см. axisdemo.
Правда, он тоже пиксели не учитывает.
VAshot писал(а):И что касается подписей, было бы не плохо иметь возможность двухстрочных..
Добавлю, надо только придумать интерфейс -- как указать, сколько в подписи строк и где её разбивать?
Например, как это сделно в Delphi?
Для axis.Title можно сделать из Caption StringList, хотя это нарушит совместимость,
а вот что для Marks делать?
Можно воспользоваться TDateTimeIntervalChartSource, который автоматически
подбирает шаг изменения даты в соответствии с текущим масштабом, см. axisdemo.
Смотрел его, даже не учитывая, что проблема эта и там, уж очень для специфических задач штука, для обычных - показалось бредовым вариантом)
OnMarkToText гибче, всё равно писать ручками.
Можно произвольно привязать метки к значениям координаты (в мировой системе)
с помощью свойства Source.
Не совсем понял, поясните пожалуйста. С привязкой к экранным координатам более понятно, типа того, как у меня было. Знаем ширину окна, знаем ширину подписи, подбираем их подходящее число и координаты. И в таком случае, опционально, можно было бы крайние подписи размещать на углах графика, для красивости и понимания, какой диапазон отображается.
а вот что для Marks делать?
На мой взгляд, всё очень просто, разбивать по общепринятым "#13#10" или "\n".
Сложнее с реализацией, осей-то сейчас может быть несколько рядом, и высота их может быть разная.
Title можно так же. Для простоты, можно ограничится одним или двумя разрывами, хотя не суть.
Например, как это сделно в Delphi?
Не могу сказать, последний раз с ним работа года три назад, а с графиками лет 6-7 и то примитивными.
Да, маленький глюк нашел: http://bugs.freepascal.org/view.php?id=18594.
VAshot писал(а):
...TDateTimeIntervalChartSource...
Смотрел его, даже не учитывая, что проблема эта и там, уж очень для специфических задач штука, для обычных - показалось бредовым вариантом)
OnMarkToText гибче, всё равно писать ручками.
Основная задача -- сделать, чтобы разумно работало масштабирование на оси с датами, особенно при широком интервале значений масштаба.
VAshot писал(а):
...свойства Source...
Не совсем понял, поясните пожалуйста.
Можно конкретно указать координаты (не в пикселях, а на оси), где будут расположены метки.
См. axisdemo, страницу Customized marks.
VAshot писал(а):
На мой взгляд, всё очень просто, разбивать по общепринятым "#13#10" или "\n".
Сложнее с реализацией, осей-то сейчас может быть несколько рядом
Да нет, у меня там сейчас всё модульно, так что реализация элементарная.
Я не уверен, насколько переносимо разбиение на строки с помощью DrawText,
так что разбил руками. См. закладку Multiline в labelsdemo начиная с ревизии 29184.
Должно сразу работать и на axis, и на series, и на title.
VAshot писал(а):
Да, маленький глюк нашел: http://bugs.freepascal.org/view.php?id=18594.
Исправил. Please test and close if ok -- Я его номинирую для бэкпорта в 0.9.30.
Ask писал(а):Основная задача -- сделать, чтобы разумно работало масштабирование на оси с датами, особенно при широком интервале значений масштаба.
Возможно не разобрался, но при увеличении видны только дни, а в каком месяце и году? Не хватает настроек по формату отображения для каждого этапа увеличения.
Ask писал(а):Можно конкретно указать координаты (не в пикселях, а на оси), где будут расположены метки.
Полезно, но как быть с перекрывающими друг друга записями, исключать?
- Little_Roo
- энтузиаст
- Сообщения: 639
- Зарегистрирован: 27.02.2009 18:56:36
- Откуда: Санкт-Петербург
Ask писал(а):Конечно, OnMarkToText -- это самый общий случай, хоть обработчик и не сохраняется
А как можно вывести из базы данных столбчатую диаграмму (желательно горизонтальную), чтобы на оси Y выводились фамилии (...FieldByName('FAM').AsString, а по Х - число (...FieldByName('BALL').AsFloat ?
Пробовал DbChartSource, но он ругается на строковое поле ...Да и получилось только вертикальную диаграмму, и на каждый столбец диаграммы выводил последнюю фамилию из выборки
Я понимаю, что у меня и лыжи не едут, и....
Ткните носом - в Delphi это легко реализовывалось....
Lazarus 0.9.31 r29190 FPC 2.4.3 i386-win32-win32/win64
Little_Roo писал(а):столбчатую диаграмму (желательно горизонтальную)
См. rotatedemo
Little_Roo писал(а):чтобы на оси Y выводились фамилии ...FieldByName('FAM').AsString
Установи FieldText='FAM', ну и дальше стиль меток smsLabel или аналогичный
Добавлено спустя 3 минуты 14 секунд:
VAshot писал(а):Возможно не разобрался, но при увеличении видны только дни, а в каком месяце и году? Не хватает настроек по формату отображения для каждого этапа увеличения.
Не только дни, а и часы, минуты, секунды по мере приближения.
Да, наверное более подробные настройки могли бы пригодиться -- тут опять же в реализации всё просто,
нужно только продумать интерфейс.
VAshot писал(а):Ask писал(а):Можно конкретно указать координаты (не в пикселях, а на оси), где будут расположены метки.
Полезно, но как быть с перекрывающими друг друга записями, исключать?
Пока да. В перспективе есть план сделать опцию "сдвинуть", но это требует существенных архитектурных изменений.
- Little_Roo
- энтузиаст
- Сообщения: 639
- Зарегистрирован: 27.02.2009 18:56:36
- Откуда: Санкт-Петербург
Ask писал(а):Little_Roo писал(а):столбчатую диаграмму (желательно горизонтальную)
См. rotatedemo
За подсказку БОЛЬШОЙ тнх
Но поворот диаграммы пока не прошел - ну это видимо Я дурак...
А вот для придурков
Прошу пардону, но наследия дельфей за штаны кусают
Little_Roo писал(а):Но поворот диаграммы пока не прошел
Установи у BarSeries свойства:
AxisIndexX = 0
AxisIndexY = 1
Little_Roo писал(а):в опциях чарта можно ли сделать галку - вертикальная диаграмма
В принципе можно, но не хочется -- избыточно и может привести к путанице.
Лучше сделать что-то типа Wizard с наиболее частыми задачами.
Или написать наконец документацию
P.S. Сорри за поучение, но Я преподаватель, удержаться трудно:
сообщать "Я дурак" бесполезно, лучше скажи конкретно, что пробовал сделать и что не получилось.
- Little_Roo
- энтузиаст
- Сообщения: 639
- Зарегистрирован: 27.02.2009 18:56:36
- Откуда: Санкт-Петербург
Ask писал(а):Little_Roo писал(а):в опциях чарта можно ли сделать галку - вертикальная диаграмма
В принципе можно, но не хочется -- избыточно и может привести к путанице.
Лучше сделать что-то типа Wizard с наиболее частыми задачами.
Или написать наконец документацию
Сделать Wizard - по принципу и по подобию TeeChart - это великая вещь - особенно если часть настроек под выбранную тему сразу ставить по нужному дефолту, а не нужные скрывать нафиг
Вот тогда AChart станет просто супер компонентом (главное, чтоб НЕ стал коммерческим)
Ask писал(а):P.S. Сорри за поучение, но Я преподаватель, удержаться трудно:
сообщать "Я дурак" бесполезно, лучше скажи конкретно, что пробовал сделать и что не получилось.
Увы мне, я тоже учитель
Вот мой папа и заявляет - "Тот, кто говорит, что он дурак, то он уже не дурак, а самокритичная личность"
А вот как сделать бы клонирование серии - т.е. настроил одну серию (а их нужно штук ...дцать) - и менять только те свойства, которые только в данной серии меняются....
(ну это я уж в будущее смотрю)
