Reputation:
I'm using Borland C++Builder 2006 with TChart Standard 4.04, and I have a problem. I have a TChart that, when calculating where the user clicked on it, it fails doing this calculations, and it seems there is no way to avoid this problem. In fact, my feeling is that nobody clicks on the chart, and the event is thrown internally by itself.
Attached you can find the error details, and I would like to know what is doing exactly, in order to try to avoid the error. I have tried avoiding this problem disconnecting the series from the chart (ParentChart property to NULL while updating the content of the series), but it still happens.
Also, you can find, in the same attached image, the problematic chart (marked in red). Below, a little explanation of how is that chart. It contains 3 series:
1 TPointSeries:
This series has only one point, in the same position that the selected one in next TPointSeries.
It shows bigger the selected point, and the top chart (which doesn't generate any problem) shows the details of the selected item.
1 TPointSeries
1 TLineSeries
This series represents the evolution, and has one point for each study carried out on a patient.
At the end, it joins all the points of the previous series.
And here, is the image
I have been able to recreate the problem with the next simple unit. It contains a chart that shows 2 or 3 points. In order to change between 2 and 3 points, you can use buttons, or click on any point of the series. Each time that chart must be updated, all series are emptied, and filled again with the required data. In this state, it doesn't fail, independently if you use the buttons or clicks on series points.
But, the form has also a check box that, simply, adds a waiting of 1 second after updating the chart. In this case, when there are 3 points in the chart and you click on any point to change to 2 points, the chart is updated and stopped for 1 second. After this second, the error comes up.
Here, code of file .h:
//---------------------------------------------------------------------------
#ifndef MainH
#define MainH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <vector.h>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <Chart.hpp>
#include <ExtCtrls.hpp>
#include <Series.hpp>
#include <TeEngine.hpp>
#include <TeeProcs.hpp>
//---------------------------------------------------------------------------
struct TItemInChart {
int IdMeasurement;
int Group;
TDateTime DateTime;
};
class TForm1 : public TForm
{
__published: // IDE-managed Components
TChart *Chart;
TLineSeries *Series_BgLine;
TPointSeries *Series_Points;
TPointSeries *Series_SelectedPoint;
TButton *Button2p;
TButton *Button3p;
TCheckBox *cbSleepAfterUpdate;
void __fastcall Button2pClick(TObject *Sender);
void __fastcall ChartClickSeries(TCustomChart *Sender,
TChartSeries *Series, int ValueIndex, TMouseButton Button,
TShiftState Shift, int X, int Y);
void __fastcall FormShow(TObject *Sender);
private: // User declarations
vector<TItemInChart*> vSetOf2Items;
vector<TItemInChart*> vSetOf3Items;
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Here, code of file .cpp:
//---------------------------------------------------------------------------
#include <vcl.h>
#include <Math.hpp>
#pragma hdrstop
#include "Main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
//Set of 2 elements
TItemInChart *tf = new TItemInChart();
tf->IdMeasurement = 21;
tf->DateTime = Now();
tf->Group = 1;
vSetOf2Items.push_back(tf);
tf = new TItemInChart();
tf->IdMeasurement = 2;
tf->DateTime = Now() + 1;
tf->Group = 2;
vSetOf2Items.push_back(tf);
//Set of 3 elements
tf = new TItemInChart();
tf->IdMeasurement = 31;
tf->DateTime = Now();
tf->Group = 1;
vSetOf3Items.push_back(tf);
tf = new TItemInChart();
tf->IdMeasurement = 32;
tf->DateTime = Now() + 1;
tf->Group = 2;
vSetOf3Items.push_back(tf);
tf = new TItemInChart();
tf->IdMeasurement = 33;
tf->DateTime = Now() + 2;
tf->Group = 3;
vSetOf3Items.push_back(tf);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2pClick(TObject *Sender)
{
//Disconecting the series and the chart
Series_BgLine->ParentChart = NULL;
Series_Points->ParentChart = NULL;
Series_SelectedPoint->ParentChart = NULL;
//Deleting alle xisnting data
Series_Points->Clear();
Series_SelectedPoint->Clear();
Series_BgLine->Clear();
//Deciding which data I'm goping to load
vector<TItemInChart*> vSetOfItems;
if (Sender == Button2p) {
vSetOfItems = vSetOf2Items;
}
else{
vSetOfItems = vSetOf3Items;
}
//Loading the data.
TItemInChart *iic;
for (int i = 0; i < vSetOfItems.size(); i++){
iic = vSetOfItems[i];
//Adding to series
Series_Points->AddXY(i+1, iic->Group, "", clRed);
Series_BgLine->AddXY(i+1, iic->Group, "", clWhite);
if ( (iic->IdMeasurement == 21) || (iic->IdMeasurement == 33) ) {
//Adding to selected point serie.
Series_SelectedPoint->Clear();
Series_SelectedPoint->AddXY(i + 1, iic->Group, "", clRed);
}
}
//Conencting again the series with the chart
Series_BgLine->ParentChart = Chart;
Series_Points->ParentChart = Chart;
Series_SelectedPoint->ParentChart = Chart;
//Waiting only if user wants
if (cbSleepAfterUpdate->Checked) {
Sleep(1000);
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ChartClickSeries(TCustomChart *Sender,
TChartSeries *Series, int ValueIndex, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
//When clicking on any serie point, we change from 2 to 3 points, and vice-versa.
if (Series_BgLine->Count() <= 2) {
Button2pClick(Button3p);
}
else{
Button2pClick(Button2p);
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormShow(TObject *Sender)
{
//When starting, we fill the chart with 3 points
Button2pClick(Button3p);
}
//---------------------------------------------------------------------------
Here, code of file .dfm:
object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 328
ClientWidth = 556
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnShow = FormShow
PixelsPerInch = 96
TextHeight = 13
object Chart: TChart
Left = -11
Top = 0
Width = 565
Height = 292
AllowPanning = pmHorizontal
AllowZoom = False
BackWall.Brush.Color = clWhite
BackWall.Color = 7436151
BackWall.Pen.Color = clGray
BottomWall.Color = 7436151
Foot.AdjustFrame = False
Foot.Visible = False
MarginBottom = 3
MarginLeft = 10
MarginTop = 3
Title.AdjustFrame = False
Title.Color = 7436151
Title.Font.Charset = DEFAULT_CHARSET
Title.Font.Color = clWhite
Title.Font.Height = -11
Title.Font.Name = 'Arial'
Title.Font.Style = []
Title.Text.Strings = (
'HISTORY')
OnClickSeries = ChartClickSeries
BackColor = 7436151
BottomAxis.Automatic = False
BottomAxis.AutomaticMaximum = False
BottomAxis.AutomaticMinimum = False
BottomAxis.Axis.Color = clGray
BottomAxis.Axis.Width = 1
BottomAxis.AxisValuesFormat = '0'
BottomAxis.ExactDateTime = False
BottomAxis.Increment = 1.000000000000000000
BottomAxis.LabelsAngle = 90
BottomAxis.LabelsFont.Charset = ANSI_CHARSET
BottomAxis.LabelsFont.Color = clWhite
BottomAxis.LabelsFont.Height = -11
BottomAxis.LabelsFont.Name = 'Arial'
BottomAxis.LabelsFont.Style = []
BottomAxis.LabelsMultiLine = True
BottomAxis.LabelsSeparation = 1
BottomAxis.LabelsSize = 66
BottomAxis.LabelStyle = talValue
BottomAxis.Maximum = 7.000000000000000000
BottomAxis.Minimum = 1.000000000000000000
BottomAxis.MinorTickCount = 0
BottomAxis.MinorTickLength = 0
BottomAxis.StartPosition = 5.000000000000000000
BottomAxis.EndPosition = 95.000000000000000000
Frame.Color = clGray
LeftAxis.Automatic = False
LeftAxis.AutomaticMaximum = False
LeftAxis.AutomaticMinimum = False
LeftAxis.Axis.Color = clGray
LeftAxis.Axis.Width = 1
LeftAxis.ExactDateTime = False
LeftAxis.Increment = 1.000000000000000000
LeftAxis.LabelsFont.Charset = DEFAULT_CHARSET
LeftAxis.LabelsFont.Color = clWhite
LeftAxis.LabelsFont.Height = -11
LeftAxis.LabelsFont.Name = 'Arial'
LeftAxis.LabelsFont.Style = []
LeftAxis.LabelsMultiLine = True
LeftAxis.Maximum = 5.000000000000000000
LeftAxis.MinorTickCount = 0
LeftAxis.MinorTickLength = 0
LeftAxis.StartPosition = 10.000000000000000000
LeftAxis.EndPosition = 90.000000000000000000
LeftAxis.RoundFirstLabel = False
Legend.Visible = False
MaxPointsPerPage = 8
ScaleLastPage = False
View3D = False
View3DWalls = False
BevelOuter = bvNone
Color = 7436151
TabOrder = 0
object Series_BgLine: TLineSeries
Marks.ArrowLength = 8
Marks.Visible = False
SeriesColor = clWhite
Title = 'Series_BgLine'
Pointer.InflateMargins = True
Pointer.Style = psRectangle
Pointer.Visible = False
XValues.DateTime = False
XValues.Name = 'X'
XValues.Multiplier = 1.000000000000000000
XValues.Order = loAscending
YValues.DateTime = False
YValues.Name = 'Y'
YValues.Multiplier = 1.000000000000000000
YValues.Order = loNone
end
object Series_Points: TPointSeries
Cursor = crHandPoint
Marks.ArrowLength = 0
Marks.Visible = False
SeriesColor = 4227327
Title = 'Series_Points'
Pointer.HorizSize = 7
Pointer.InflateMargins = True
Pointer.Pen.Color = clRed
Pointer.Pen.Visible = False
Pointer.Style = psCircle
Pointer.VertSize = 7
Pointer.Visible = True
XValues.DateTime = False
XValues.Name = 'X'
XValues.Multiplier = 1.000000000000000000
XValues.Order = loAscending
YValues.DateTime = False
YValues.Name = 'Y'
YValues.Multiplier = 1.000000000000000000
YValues.Order = loNone
end
object Series_SelectedPoint: TPointSeries
Marks.ArrowLength = 0
Marks.Visible = False
SeriesColor = clMaroon
Title = 'Series_SelectedPoint'
Pointer.HorizSize = 11
Pointer.InflateMargins = True
Pointer.Pen.Color = clRed
Pointer.Pen.Visible = False
Pointer.Style = psCircle
Pointer.VertSize = 11
Pointer.Visible = True
XValues.DateTime = False
XValues.Name = 'X'
XValues.Multiplier = 1.000000000000000000
XValues.Order = loAscending
YValues.DateTime = False
YValues.Name = 'Y'
YValues.Multiplier = 1.000000000000000000
YValues.Order = loNone
end
end
object Button2p: TButton
Left = 24
Top = 298
Width = 99
Height = 25
Caption = 'Button 2 points'
TabOrder = 1
OnClick = Button2pClick
end
object Button3p: TButton
Left = 129
Top = 297
Width = 105
Height = 25
Caption = 'Button 3 Points'
TabOrder = 2
OnClick = Button2pClick
end
object cbSleepAfterUpdate: TCheckBox
Left = 416
Top = 304
Width = 121
Height = 17
Caption = 'Sleep after the update'
TabOrder = 3
end
end
Upvotes: 0
Views: 190