03-08-2012 09:30 AM
Hi,
I have 4 of "waveformPlot.PlotY"
I can easily add 4 cursors....one for each plot but that looks a mess. What I'd like is just one cursor with a label for each plot?
Is that possible?
03-08-2012 09:38 AM
Hi there,
Could you please provide a screen shot of your window how you are expecting the cursor to look like?
Regards,
Vijet Patankar,
National Instruments
03-08-2012 09:55 AM
So you see here I am showing several trends (may be more than this in the final app). The cursor control seems very handy but rather than have 4 seperate cursors I would like that one cursor to just show the value on each trend at the current position.
Either this or a suggestion of a better way. Perhap some NumericEdit controls to the side with the legend showing values for each trend at the current cursor position. I actually tried this first but it seemed like you could only bind the value of a Gauge control to a NumericEdit control? Perhaps I was missing something though...
03-08-2012 11:50 AM - edited 03-08-2012 11:51 AM
Hi there,
By default the xy cursor is attached only to only plot. But if you want to play around with it to suite your needs, you will have to write some code for it.
I typed some code and got the following screenshot. Note that I have only one cursor attached to the first plot.
I guess this is what you were looking for.
The code looks huge, but it is easy to understand. Here it is..
using System; using System.Drawing; using System.Windows.Forms; using NationalInstruments.UI; using System.Collections; using NationalInstruments.UI.WindowsForms; namespace SingleCursorForMultiplePlots { public partial class Form1 : Form { MultiPlotCursor cursor = new MultiPlotCursor(); public Form1() { InitializeComponent(); cursor.Plot = waveformGraph1.Plots[0]; cursor.Color = Color.FromArgb(100, waveformGraph1.Plots[0].LineColor); cursor.LabelVisible = true; cursor.Visible = true; cursor.SnapMode = CursorSnapMode.ToPlot; waveformGraph1.Cursors.Add(cursor); // add other plots. cursor.AddPlotToGraph(waveformPlot2); cursor.AddPlotToGraph(waveformPlot3); cursor.AddPlotToGraph(waveformPlot4); } private void button1_Click(object sender, EventArgs e) { PlotData(); cursor.XPosition = 100; } private void PlotData() { foreach(WaveformPlot p in waveformGraph1.Plots) { p.PlotY(GetMyRandomData()); } } // Generate some random data; Random r = new Random(); private double[] GetMyRandomData() { double amplitude = r.NextDouble() * 100 + 10; double phase = r.NextDouble() * 100; int count = 1000; double[] data = new double[count]; for (int i = 0; i < count; i++) { data[i] = amplitude * Math.Sin(phase + i * 0.01) + r.NextDouble() * 4; } return data; } } // My custom cursor which can be attached to multiple plots!! public class MultiPlotCursor : XYCursor { ArrayList plots = new ArrayList(); private static Color DefaultHorizontalCursorColor = Color.FromArgb(100, Color.White); private static Pen CursorPen = new Pen(new SolidBrush(DefaultHorizontalCursorColor), 3); private static Brush CursorBrush = new SolidBrush(DefaultHorizontalCursorColor); public MultiPlotCursor() { } public void AddPlotToGraph(XYPlot plot) { // add whatever plots you want to add. // handle the error case that the plots belongs to same graph. plots.Add(plot); } public new XYPlot Plot { get { return base.Plot; } set { if(value != null) { // Add the plot to the list first. // just so that we don't miss it. AddPlotToGraph(value); base.Plot = value; } } } protected override void OnBeforeDraw(BeforeDrawXYCursorEventArgs e) { DrawMultiPlotCursors(e); } private void DrawMultiPlotCursors(BeforeDrawXYCursorEventArgs e) { DrawCursorForCurrentPlot(e); DrawCursorForOtherPlots(e); } private WaveformGraph MyGraph { get { if (Plot != null && Plot.Owner != null) { return Plot.Owner as WaveformGraph; } return null; } } private void DrawCursorForOtherPlots(BeforeDrawXYCursorEventArgs e) { if (plots.Count > 1) { for (int i = 1; i < plots.Count; i++ ) { WaveformPlot plot = plots[i] as WaveformPlot; if (plot.HistoryCount > 0) { // do only if data is plotted. // otherwise cursor can be drawn anywhere you want. double xData = 0; double yData = 0; ///////////////////////////////////////////////////////////// // SOME CALCULATIONS for getting pixel coordinates of the data for our cursors for the data on the other plots. // this is actually the index of the xData. int location = (int)this.XPosition; // get the YData from the plot. plot.GetDataPoint(location, out xData, out yData); // Convert the value in data coordinate into the device (pixel) coordinates. PointF point = plot.MapDataPoint(MyGraph.PlotAreaBounds, xData, yData); ///////////////////////////////////////////////////////////// // Hurreeeyy.. !! // Basically, here We got the horizontal line where the line should be drawn for the cursor for the other plots. // So draw the line there..!! // here is how it is done.. // get the two ends of the line PointF p1 = new PointF(MyGraph.PlotAreaBounds.Left, point.Y); PointF p2 = new PointF(MyGraph.PlotAreaBounds.Right, point.Y); // Change the color according to the plot color. // Cursor looks neat. Color color = Color.FromArgb(100, plot.LineColor); CursorPen.Color = color; // draw the line!! e.Graphics.DrawLine(CursorPen, p1, p2); ///////////////////////////////////////////////////////////// // If you want the label to be drawn as well. // Here is how you do it. // Set color (CursorBrush as SolidBrush).Color = plot.LineColor; // decide what you want to draw string labelString = String.Format("({0}, {1})", xData, yData.ToString("F3")); // decide where to draw it.. We already have the data location in pixels, just offset it by (10, -20). Point labelLocation = new Point((int)point.X + 10, (int)point.Y - 20); // just draw the string!!! e.Graphics.DrawString(labelString, MyGraph.Font, CursorBrush, labelLocation); } } } } private void DrawCursorForCurrentPlot(BeforeDrawXYCursorEventArgs e) { base.OnBeforeDraw(e); } } }
Hope this helps!
Regards
Vijet Patankar,
National Instruments.
03-09-2012 01:26 AM
that is great, thank you so much for the help!