please understand that I know there are other threads concerning this issue, but my needs are different.
Basically before I seen people saying to implement a scroll bar with MSChart they use the
.Size = ...
or
.View = ...
But, this make a scroll bar automatically apprear, and this scroll bar contains a button that when clicked causes the bar to vanish, making the chart show all data, and no way of bringing back the scroll bar to the chart without restarting the app.
So I ask, please, Is there a way to incorportate a horizontal scroll bar on the X-axis of my Chart? I am needing on so that I can view my chart data on blocks of 100 second blocks.
i.e. 0 - 100, then click sroll bar will bring me to 100 - 200 block.
Thank you in advance guys!!!!! im coding in C# also
Here's an example of what you need:
(to try it, just create a form, add a mschart and call the following method)
private void FillChart()
{
int blockSize = 100;
// generates random data (i.e. 30 * blockSize random numbers)
Random rand = new Random();
var valuesArray = Enumerable.Range(0, blockSize * 30).Select(x => rand.Next(1, 10)).ToArray();
// clear the chart
chart1.Series.Clear();
// fill the chart
var series = chart1.Series.Add("My Series");
series.ChartType = SeriesChartType.Line;
series.XValueType = ChartValueType.Int32;
for (int i = 0; i < valuesArray.Length; i++)
series.Points.AddXY(i, valuesArray[i]);
var chartArea = chart1.ChartAreas[series.ChartArea];
// set view range to [0,max]
chartArea.AxisX.Minimum = 0;
chartArea.AxisX.Maximum = valuesArray.Length;
// enable autoscroll
chartArea.CursorX.AutoScroll = true;
// let's zoom to [0,blockSize] (e.g. [0,100])
chartArea.AxisX.ScaleView.Zoomable = true;
chartArea.AxisX.ScaleView.SizeType = DateTimeIntervalType.Number;
int position = 0;
int size = blockSize;
chartArea.AxisX.ScaleView.Zoom(position, size);
// disable zoom-reset button (only scrollbar's arrows are available)
chartArea.AxisX.ScrollBar.ButtonStyle = ScrollBarButtonStyles.SmallScroll;
// set scrollbar small change to blockSize (e.g. 100)
chartArea.AxisX.ScaleView.SmallScrollSize = blockSize;
}
Snapshot:
I would do it like this:
if (series1.Points.Count > 2 && chartArea1.AxisX.Maximum - chartArea1.AxisX.Minimum > chartArea1.AxisX.ScaleView.Size)
{
chartArea1.AxisX.ScrollBar.Enabled = true;
}
else
{
chartArea1.AxisX.ScrollBar.Enabled = false;
}
So when you added points more than your scaleview - scrollbar is appear
I worked out my own way for that. Hope it helps you:
Add your chart to a Panel.
Set the AutoScroll property of the panel to true with panelName.AutoScroll=true;
Size the chart properly in the panel.
You can now use the panel's scrollbar as if it were the chart's!
If data gets added continuously(e.g. with a timer or so), add this to the timer's tick event:
chartName.Size = new Size(width++, height++); where int width = chartName.Width; and int height = chartName.Height;
Related
Sorry, I'm not good at writing with English.
I've tried to make real time candle stick chart and almost completed.
But, there are a few problems.
When new data comes in, my program works, but it only shows half the width of the last candle.
I can then move the scroll bar to the end to see the finished bar. I don't know where to touch.
When the chart area is zoomed, the length of the x-axis changes slightly when data is received.
I want to fix the size of the area where the candle is displayed.
The following are some of the sources:
private void RealChart(Chart chart)
{
int a = chtMain.Series["BaseCandle"].Points.Count;
double yMinValue = double.MaxValue;
double yMaxValue = double.MinValue;
for (int i = 0; i < a; i++)
{
Series s = chtMain.Series["BaseCandle"];
if (i < s.Points.Count)
{
yMaxValue = Math.Max(yMaxValue, s.Points[i].YValues[0]);
yMinValue = Math.Min(yMinValue, s.Points[i].YValues[1]);
}
}
chtMain.ChartAreas["ChartArea1"].AxisY.Maximum = yMaxValue + Math.Abs(yMaxValue * 0.05);
chtMain.ChartAreas["ChartArea1"].AxisY.Minimum = yMinValue - Math.Abs(yMinValue * 0.05);
chtMain.ChartAreas["ChartArea1"].AxisX.ScaleView.Scroll(a);
}
I'm adding buttons dynamically to a Form and am trying to lay the out side by side. I'm perfectly content with using the latest Button.Right as a starting point for the next button (with a margin left between of course), but the buttons have to adjust to fit the text.
So, what I'm doing is setting the AutoResize property to true and then storing the Right property, which however does not work because I guess the resizing doesn't happen until the button is drawn (I think). I tried Invalidate(), Refresh(), Update() and I think a couple more functions, and of course all together, but to no avail, I still get the old position and the next button starts beneath this one.
So the question is, after setting AutoResize to true on a Forms component, how do I force it to resize so I can grab the new Width/Right without waiting for the window to be redrawn?
Thanks in advance!
Note: If all else fails I'll do a rough approximation of the width of the buttons based on the string's length, so don't bother with something too fancy as a solution, it's not a requirement that it is perfect
You can use the Control's GetPreferredSize Method to obtain the final auto-sized dimensions. The Font property must either be explicitly set or the Control must be parented to a displayed control such that it can inherit the Font to use in the layout. In the following example, the control's Parent property is set so that it inherits the parent control's Font.
private Random rnd = new Random(1000);
private void button1_Click(object sender, EventArgs e)
{
const Int32 xDelta = 5; // the horizontal distance between the added Buttons
Int32 y = button1.Location.Y + 5 + button1.Height;
Int32 x = button1.Location.X;
Point loc = new Point(x, y);
this.SuspendLayout(); // this is Form that is the Parent container of the Buttons
for (Int32 i = 1; i <= 10; i++)
{
Button btn = new Button { Parent = this, AutoSize = true, AutoSizeMode = AutoSizeMode.GrowAndShrink };
btn.Text = new string('A', rnd.Next(1, 21));
btn.Location = loc;
Size sz = btn.GetPreferredSize(Size.Empty); // the size of btn based on Font and Text
loc.Offset(sz.Width + xDelta, 0);
}
this.ResumeLayout(true);
}
I have made a chart which dynamically draw a spike when data received.
In this chart I have made a scrollbar, so only 20 datapoints get shown at on time.
public void Chart()
{
ChartArea mov = SleepMovChar.ChartAreas["Movement"];
mov.AxisX.ScrollBar.Size = 12;
mov.AxisX.ScrollBar.ButtonStyle = ScrollBarButtonStyles.SmallScroll;
mov.AxisX.ScrollBar.ButtonStyle = ScrollBarButtonStyles.All ^ ScrollBarButtonStyles.ResetZoom;
mov.AxisX.ScrollBar.IsPositionedInside = true;
mov.AxisX.ScrollBar.Enabled = true;
mov.AxisX.ScaleView.Size = 20;
}
My problem is, that I want that scrollbar to move to right when data received. At the time now, it moves to left, so the first data is shown. I just want that the latest data is shown instead, so that the scrollbar follows the data receive.
If you want the visible area to follow the new data like in an oscilloscope, you can set the scroll position :
Series S1 = SleepMovChar.Series["yourSeriesByNameOrNumber"];
mov.AxisX.ScaleView.Position = S1.Points.Count - mov.AxisX.ScaleView.Size;
You will need to repeat this whenever you have added data points..
I am using mschart to display 10 lines with up to 60,000 points of data each. There is a single ChartArea and an individual Series for each line, set as type FastLine.
Initial performance is very good, with the chart loading almost instantly. The problems start when any sort of interaction is required. In my case this means CursorX position / selection is changed. The GUI thread goes to ~100% usage (a whole core) until the cursor stops moving. During this time the graph updates sporadically. No additional code or functions are being called.
After profiling the application to see where all of the CPU time is being used, it would appear that every time the cursor is moved the whole chart has to be redrawn. All 10 * 60,000 points of data. While this is reasonable with just a few thousand points of data to draw, it doesn't scale very well at all. Changing the cursors Interval value doesn't seem to make any difference.
Are there any changes I can make to fix / avoid this performance issue? If not, can you recommend any other charting libraries?
//EDIT//
As requested, here is some test code that displays the same issues as mentioned. All that is required is a chart called chart1 exists. Setting CursorX.IsUserEnabled and CursorX.IsUserSelectionEnabled to true allows for the (problematic) interactions to take place:
public MainForm()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
//Set up chart and add values
ChartArea ca = chart1.ChartAreas.Add("Data");
ca.AxisX.IsMarginVisible = false;
ca.CursorX.Interval = 0.001;
ca.CursorX.IsUserEnabled = true;
ca.CursorX.IsUserSelectionEnabled = true;
ca.AxisX.ScaleView.Zoomable = false;
for (int i = 0; i < 10; i++)
{
Series s = new Series("Series_" + i.ToString());
s.ChartArea = ca.Name;
s.ChartType = SeriesChartType.FastLine;
for (int p = 0; p < _maxPoints; p++)
{
double x = p / 100.0; //(10ms steps)
double y = p * (1 + i);
s.Points.AddXY(x, y);
}
chart1.Series.Add(s);
}
}
The larger the value for _maxPoints, the worse the problem becomes.
I'm developing several bar charts using chart controls in C#, one of which holds a series of ~2300 data points. In order to be able to properly display custom labels for each data point, I expanded the height of the chart to be 10000. However, it's now producing quite a large sized header and footer for the chart, as seen below:
When I set the chart to resume having a more normal height of 500, though, the title size goes back to being more reasonable. How can I manually adjust the title size?
Here's my code for the chart properties:
Chart chart = new Chart();
chart.Width = 1000;
chart.Height = 10000;
chart.BackColor = Color.FromArgb(211, 223, 240);
chart.BorderlineDashStyle = ChartDashStyle.Solid;
chart.BackGradientStyle = GradientStyle.TopBottom;
chart.BorderlineWidth = 1;
chart.Palette = ChartColorPalette.Bright;
chart.BorderlineColor = Color.FromArgb(26, 59, 105);
chart.RenderType = RenderType.BinaryStreaming;
chart.BorderSkin.SkinStyle = BorderSkinStyle.Emboss;
chart.AntiAliasing = AntiAliasingStyles.All;
chart.TextAntiAliasingQuality = TextAntiAliasingQuality.Normal;
chart.Titles.Add("Hit Rate");
chart.IsSoftShadows = true;
chart.ChartAreas.Add("Left");
chart.ChartAreas["Left"].AxisX.Title = "Market Area";
chart.ChartAreas["Left"].AxisY.Title = "Hit Percentage";
UPDATE: I have added this to my code...
chart.ChartAreas["Left"].InnerPlotPosition.X = 5;
chart.ChartAreas["Left"].InnerPlotPosition.Y = 0f;
which has helped somewhat. In addition, I have found that it is not the size of the title in and of itself that is causing the problem. The height of the title is actually quite normal. Instead it is all the blank space allocated to the chart above the actual graphing area.
Let's try this :
chart.Titles[0].Position.Auto = false;
chart.Titles[0].Position.Width = 60; //change the size you want
auto = false means you manually calculate the location. I think by default the width of the title is 50% and 50% of the chart.
Ludo
Instead of setting the height and width of the chart manually why don't you leave it to set automatically according to the content and set the below:
chart.ChartAreas[0].AxisX.Interval = 1;
chart.ChartAreas[0].AxisY.Interval = 1;
(here i'm choosing chart area 0, change it according to your code)
As you add the above code do not set the height and width of the chart.
Let me know in case of issues