I want to show a table for Box Plot containing Values such as mean Median , S.D , Range etc.
The Data Table tool shows only X, X2 data doesn't allow for customization data.I am trying too use Custom Legend Tool using which we can create Table specifying Grid Row and Column. Can anyone let me know how we can enter data into the table.
Thanks
Akshay
If I'm not wrong, you are using VC++. The CustomLegend tool is a quite new tool and I'm afraid there are some features missing in it for VC++.
I've added it to the wish list to be implemented in future releases (TA05015410/B395).
In the meanwhile, note TeeChart ActiveX supports custom drawing so you can manually draw your table if the other tools in the component don't allow you to draw what you exactly want to.
Custom drawing techniques basically consist on a set of methods and properties (set the Canvas Pen, Brush and Font, and draw lines, shapes or texts) to draw directly onto the canvas. These methods are commonly called at the OnAfterDraw event so the custom drawing can be redone after each repaint.
You can find examples written in VC++ under the \Examples\Visual C++\Version 6\ folder in your TeeChart ActiveX installation. Concretely, you can see a simple example of how to use custom drawing techniques in the Dragging Points project. In the DraggingDlg.cpp file you can see how some custom drawing techniques are used in the OnAfterDraw method:
void CDraggingDlg::OnAfterDrawTChart()
{
// Draw a white circle around the clicked pyramid...
if (-1 != m_ClickedBar)
{
CCanvas aCanvas = m_ctrlChart.GetCanvas();
CPen1 aPen = aCanvas.GetPen();
aPen.SetColor(RGB(255, 255, 255));
aPen.SetWidth(1);
aPen.SetStyle(psDot);
aCanvas.GetBrush().SetStyle(bsClear);
int x = m_ctrlChart.Series(0).CalcXPos(m_ClickedBar);
int y = m_ctrlChart.Series(0).CalcYPos(m_ClickedBar);
aCanvas.Ellipse(x, y, x + 40, y + 40);
}
}
Related
I have a simple program in C++ builder with VCL that i need to migrate to Firemonkey. In this application i need to draw on a TChart, but i don't know how to get it to work. My application is really simple; a user inputs data in a stringgrid and then the data is displayed in two different TChart by clicking two different buttons.
The first button click is to divide the TChart into equal parts (generally in two parts, but the user can divide the TChart into more than two parts). In the first example there is a column, with two long rectangles with texts, in it. In this example it's two rectangles with "CH PL".
The second button is supposed to draw on the same TChart this:
It's essentially two or more rectangles which go from the beginning of the chart until the end.
To make it simple i need to divide the TChart into two or more equal parts horizontally and then draw rectangles with texts on it, which is the simplest solution.
I'm really lost because by searching on the net i came across a similar problem by simply using the TChart.AfterDraw() method, but I don't know how to use it, it's not really clear.
The drawing are generated once the user clicks a button, else there should be nothing.
My method for drawing so far:
void __fastcall TForm1::rbComprChange()
{
Series5->Clear(); //used for clearing the series to regenerate them from the user input
for(int i=0;i<StringGrid1->RowCount;i++)
{
Series5->AddGantt(StrToDate(StringGrid1->Cells[4][i]),StrToDate(StringGrid1->Cells[5][i]),i,StringGrid1->Cells[1][i]);
Series5->NextTask->Value[i]=i;
}
// How and where should i draw these rectangles?!
}
Can someone guide me or explain to me how to do that either in C++ Builder or Delphi.
While using Delphi Seattle 10 and Steema TeeChart Pro VCL FMX 2016.18, I am looking to Highlight a Selection of a Line Graph (multiple series) in the way that Zooming allows / makes a square around a highlighted selection of a Line Graph to indicate which part of it to zoom into (as long as the onmousedown action is in progress).
The purpose of this would be to allow the selection to remain highlighted while the mouse is no longer being clicked, to potentially "Delete" the highlighted Data points. All I need this for is to obtain the (X0 Y0 X1 Y1) values to possibly obtain the CalcPosPoint(X) and remove all the points inside. The data is currently obtained through a Record Struct (Memory Mapped) file, and it will there for be used to set/check for a property "deleted" to indicate on the next redraw of the graph which rows to completely ignore and which to continue printing.
I hope to be able to do this (select from 1 chart), and have it simultaneously draw on multiple graphs. I have tried to look for an example of this feature through the use of TSelectorTool (FMXTee). One of the pages I found referring to such a tool is Interactive data point selection as well as Multiple selections with Selector Tool
And my second question has to do with TeeCharts directly. Where would I find fmx240.bpl as TeeChart_Pro_Firemonkey_Demo.exe requires this file in order to run? I did manage to copy vcl240.bpl from "Embarcadero\Studio\18.0\bin" and put it into "Embarcadero\Studio\17.0\bin"
[Edited]
I have managed to capture / create a sample code (MVCE) from which I can now select a portion and create a square around a particular sample of graph lines.
The control graph right now is the bottom graph (Chart5). If anyone is interested in seeing the code, I have put up a pastebin sample.
PasteBin Sample Code
And a TeeCharts.tar.gz is accessible to anyone who wishes to see a sample of the code, as well as the data sample.
filetolink.com Source Files
I no longer feel the need for mathematical equation to differentiate the top graphs from the bottom (because the bottom axes are automatic where as the top are defined). I intend to only use the space which is adherent to the visible space, and do not intend to extend in either direction (left or right). That means at this point the size of the graph does not matter, because once I over populate the charts above, the position in the bottom graph would become irrelevant, and therefor I do not intend to use the bottom chart.
The next step is to save the positions of the boxes so that they can reappear when the graph is shift from left (past data) to the right (live data). And then uses the buttons above to make the appropriate action to the graphs.
I would like to know what way would be the most sufficient way to record the positions of the rectangles, so when the chart is shifted (via the ScrollBar1), the rectangles are moving with the direction of the scrollbar. But I'm sure I can achieve that.
I think I have found a solution. The red squares are only prevalent for the visual aspect, they can be drawn on, I don't need to do anything special with each chart, as I already know what the X0..Y1 parameters are, they are known from the initial chart. The problem h/e has to do with the initial chart. As long as the screens are all full, I can zoom in correctly w/ alignment with on all the charts (ZoomRect/Rectf(X0..Y1))
But what kind of equation would it take to adjust the charts that are not in the same zoom / max / min when the Chart5.Axes.Bottom.Automatic = True?
From there I just simply have to disable the immediate zoom feature, and allow buttons to become functional, to decide what the next course of action would be.
I'm drawing a chart in an iOS app and I want the gridlines to start in the x axis but end in the data point instead of extending all the way up to the top.
Is this possible?
Thanks in advance.
NC
Disclaimer: I work for ShinobiControls
The shinobicharts framework doesn't currently support this as an out-of-the-box feature.
A workaround may exist though. You may be able to add your own gridline subviews by using the SChartAxis method pixelValueForDataValue: to work out where in the plot area coordinate space you should draw your vertical line up to for a given data point.
Once you have your coordinates there are various ways you could draw your gridlines:
Add a canvas view behind or in front of the chart (depending on what effect you want). Then use your coordinates to draw your gridlines using CoreGraphics or some other drawing technique.
Create individual UIViews that each represent a gridline using your coordinates and add these behind or in front of the chart.
One thing to be aware of with this technique is that the gridlines will not automatically update when you pan and zoom. In order to do this you will need to override one of the chart's delegate methods that notify you of range changes and update your drawn gridlines to match the new data point positions.
Another potential workaround could be to use a column series to mimic gridlines. If you create a column series and feed it the same data points as your original series this will result in columns that go up to the y-value of each data point. You could then use the property interSeriesSetPadding on SChartAxisStyle to cause the columns to appear very thin.
I hope that information is useful!
An instance of TChart in Delphi does a nice job of making a graph showing points. This is the "Point" series in the TeeChart gallery.
I would like to draw lines between some, but not all, of the points.
For example, image a scatter diagram of points, which is easy to make with Delphi/TChart. My objective is to draw straight lines between some of the points.
Is this possible?
This code works:
With Chart2.ChartRect do
begin
Canvas.MoveTo(0,0);
Canvas.LineTo(500,500);
end;
The line crosses over the graph, except the line is not visible over the graph. It seems as if the graph much have its own canvas but I can't find any documentation about finding and using it.
So, I need to find the coordinates of some points, as created by TChart, then draw a line between them.
Some options:
As David Heffernan said, the best option may be to use a series that supports both line segments and pointers. TLineSeries seems to be the perfect series to do this.
The problem here is that this series draws a line segment between each two consecutive points. You can make a point to be null with setNull(index) method and this will make the pointer at that index to disappear, but the predecessor and successor line segments will disappear with it.
The easiest solution could be creating a TMyLineSeries inheriting from TLineSeries to override DrawValue method as explained here.
Add a null point after each point you want to be visible. In this option, the only points not followed by a null point would be those where you want a line segment to be drawn.
Add a TLineSeries per line segment to be drawn.
You always have the possibility to use custom drawing techniques as LU RD said.
Attempting to paint lines yourself is not the way to proceed. The design basis of charting controls is that you define the chart in logical terms and let the control deal with painting it.
So, the way to proceed is to add some line series that represent the lines you wish to be drawn. You can perfectly well add these line series in addition to the other series of your chart.
Regarding your code that attempts to paint on the chart canvas, you should be aware that painting is a delicate process. The design of the system is such that control surfaces are not persistent. Controls are painted in response to the WM_PAINT message. So, whilst you may be able to paint on a control's canvas as you please, what you paint will survive only until the next cycle. Once the control becomes invalid, it needs to repaint itself. The lesson here is, as a general rule, only to paint in response to WM_PAINT messages. Or, in OnPaint events or overridden Paint methods which are called by the VCL in response to WM_PAINT.
To interconnect some points you must follow the drawing principle, all drawing must be done in a paint event.
In TChart, best option here is to do custom drawing in the OnAfterDraw event.
procedure TForm1.Chart2AfterDraw(Sender: TObject);
begin
With Chart2.ChartRect do
begin
Canvas.MoveTo(0,0);
Canvas.LineTo(500,500);
end;
end;
If you need to know the canvas coordinates for a given point in your array of points.
MyYPosX := Series1.CalcXPos( Series1.XValue[ 0 ] ); { <-- first point }
MyYPosY := Series1.CalcYPos( Series1.YValue[ 0 ] ); { <-- first point }
There is a chapter in the TChart help that is a good introduction to custom drawing: "Custom drawing on the Chart".
From the help:
When to draw ?
The order in which you draw to the Canvas is important.
If you wish Custom drawn items to appear above Chart Series you should use the Chart OnAfterDraw event. The Chart1.OnAfterDraw event is fired each time the Chart component is redrawn, just before copying the internal bitmap to screen.
You can place Custom drawn items above the Chart grid and below the Chart Series by placing your code in the Chart OnBeforeDrawSeries event.
Key Chart Paint events:
OnBeforeDrawChart
OnBeforeDrawAxes
OnBeforeDrawSeries
OnAfterDraw
A lable sized like a rectangle with no text but has a border and is invisible (for a visual rectangle on the form around controls but not to contain the controls) or a panel?
What you want to use is a GroupBox. Not that it really matters, most likely, but a label should be cheaper than a panel.
The answer is; it doesn't matter which has the smaller footprint, and if it does you have a design problem (i.e., you have way too many controls on your form). Anyhow, you should just use the control that fits the job, in this case, a Panel or a GroupBox.
If this is really a problem, then the best way to provide a visual separation between controls is to handle each tab page's Paint event, and use e.Graphics.FillRectangle(...) to draw the separator. You would get rid of a very large number of controls that way.
If you can't do something as simple as just drawing a rectangle underneath each control on each tab page, you can write a code-generating routine that you run one time on the form, and for each tab page you generate something like this (by iterating through all the separator controls on the page):
List<Rectangle> rects = new List<Rectangle>();
rects.Add(new Rectangle(10, 40, 200, 5)); // position of first separator
rects.Add(new Rectangle(10, 80, 200, 5)); // position of second separator
// etc.
Then you copy-and-paste these generated code routines into your application, and use them for each page's Paint event, like so:
SolidBrush brush = new SolidBrush(Color.PeachPuff);
foreach (Rectangle rect in rects)
{
e.Graphics.FillRectangle(brush, rect);
}
Then you delete all the separators from your tab control. What you should end up with is an array of type List<Rectangle> (one list for each page) that you instantiate and fill in the form's Load event or its constructor (using the generated code).
I have to reiterate what Ed said, though. .Net forms can have a lot of controls on them without any real problems, so if you're running into problems stemming from having too many controls on the form, you might be better off redesigning the whole thing.