I need to draw a graph in C# by ZedGraph in VS2013.
I have created a windowns application project and added Form1.cs as win forms file.
But, when I ran the code, only an empty form was created but no graph. In debug mode, I found that Form1_Load() is not executed. Why ?
This is the C# code.
using System.Windows.Forms;
using ZedGraph;
namespace zedgraph_test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// it is not executed.
private void Form1_Load(object sender, EventArgs e)
{
Console.WriteLine("Form1_Load is called");
ZedGraph.ZedGraphControl zg1 = new ZedGraphControl();
CreateChart(zg1);
}
// definition of CreateChart
...
}
Any help would be appreciated.
UPDATE
I have tried the solution but I only got an empty form and no charts displayed in the form.
This is code of From1.cs.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ZedGraph;
namespace zedgraph_test1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Console.WriteLine("Form1_Load is called");
ZedGraph.ZedGraphControl zg1 = new ZedGraphControl();
CreateChart(zg1);
SetSize();
}
private void Form1_Resize(object sender, EventArgs e)
{
SetSize();
}
private void SetSize()
{
zg1.Location = new Point(10, 10);
// Leave a small margin around the outside of the control
zg1.Size = new Size(this.ClientRectangle.Width - 20, this.ClientRectangle.Height - 20);
}
// Call this method from the Form_Load method, passing your ZedGraphControl
public static void CreateChart(ZedGraphControl zgc)
{
GraphPane myPane = zgc.GraphPane;
// Set the title and axis labels
myPane.Title.Text = "Vertical Bars with Value Labels Above Each Bar";
myPane.XAxis.Title.Text = "Position Number";
myPane.YAxis.Title.Text = "Some Random Thing";
PointPairList list = new PointPairList();
PointPairList list2 = new PointPairList();
PointPairList list3 = new PointPairList();
Random rand = new Random();
// Generate random data for three curves
for (int i = 0; i < 5; i++)
{
double x = (double)i;
double y = rand.NextDouble() * 1000;
double y2 = rand.NextDouble() * 1000;
double y3 = rand.NextDouble() * 1000;
list.Add(x, y);
list2.Add(x, y2);
list3.Add(x, y3);
}
// create the curves
BarItem myCurve = myPane.AddBar("curve 1", list, Color.Blue);
BarItem myCurve2 = myPane.AddBar("curve 2", list2, Color.Red);
BarItem myCurve3 = myPane.AddBar("curve 3", list3, Color.Green);
// Fill the axis background with a color gradient
myPane.Chart.Fill = new Fill(Color.White,
Color.FromArgb(255, 255, 166), 45.0F);
zgc.AxisChange();
// expand the range of the Y axis slightly to accommodate the labels
myPane.YAxis.Scale.Max += myPane.YAxis.Scale.MajorStep;
// Create TextObj's to provide labels for each bar
BarItem.CreateBarLabels(myPane, false, "f0");
//Console.ReadLine();
}
private void zg1_Load(object sender, EventArgs e)
{
}
}
}
More update
I have added zedgraphControl by adding zedgraph.dll under object relational design in toolbox of VS2013.
But, all components in my toolbox are all grayed out in VS2013.
When I ran the code, I still got an empty form.
I tried the project at http://www.codeproject.com/Articles/5431/A-flexible-charting-library-for-NET
I can get the chart even though all components in my toolbox are also all grayed out in VS2013.
Remove the following lines from Form1_Load and you are good to go:
Console.WriteLine("Form1_Load is called");
ZedGraph.ZedGraphControl zg1 = new ZedGraphControl();
I guess you didn't add the event handler to Form1_Load event in Form1's Properties window (at the right bottom of the designer window), you can either do that or move CreateChart(zg1) into Form1's constructor, like this:
public Form1()
{
InitializeComponent();
CreateChart(zg1);
}
Related
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MyTest
{
public partial class Form1 : Form
{
private int x, y;
private int gap = 0;
private int startingY = 150;
private GroupBox lastGB = null;
public Form1()
{
InitializeComponent();
GroupBox gb = new GroupBox();
gb.Location = new Point(100, (lastGB == null ? startingY : lastGB.Bounds.Bottom));
gb.Size = new Size(1220, 400);
gb.BackColor = SystemColors.Window;
gb.Text = "";
gb.Font = new Font("Colonna MT", 12);
this.Controls.Add(gb);
}
It's creating a small line on the top of the groupbox and I don't want this line to show.
And I want to write some text on it in the middle of it.
How can I make it just complete white ? And how to write some text in the middle on the groupbox ?
The main idea is to create over the form a white sheet or box with text inside that's it.
It looks like your intention is to put subsequent boxes just below the last box. As mentioned, a Label would probably be best. I'd also move that code to a method you can call over and over to keep from repeating code elsewhere. You could pass a message to display in the Label. Also, don't forget to update the reference to the "last box" when ever you create a new one:
public partial class Form1 : Form
{
private int x, y;
private int gap = 0;
private int startingY = 150;
private Label lastLbl = null;
public Form1()
{
InitializeComponent();
AddLabel("Hello World");
}
private void button1_Click(object sender, EventArgs e)
{
AddLabel(DateTime.Now.ToString());
}
private void AddLabel(String msg)
{
Label lbl = new Label();
lbl.Location = new Point(100, (lastLbl == null ? startingY : lastLbl.Bounds.Bottom));
lbl.Size = new Size(1220, 400);
lbl.BackColor = Color.White;
lbl.Text = msg;
lbl.TextAlign = ContentAlignment.MiddleCenter;
lbl.Font = new Font("Colonna MT", 12);
this.Controls.Add(lbl);
lastLbl = lbl;
}
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
Today I've tried Visual Studio + WinForms (I've been using Xamarin)
I dont use designer, just create empty project and link needed libraries.
So, my timer doesn't work properly, it ticks only in minimized form.
App.cs
using System;
using System.Windows.Forms;
namespace Line
{
class App
{
[STAThread]
public static void Main()
{
Application.Run(new Window());
}
}
}
Window.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
namespace Line
{
class Window : Form
{
Timer timer;
PictureBox pictureBox;
Bitmap bmp;
public struct Circle
{
public PointF position;
public SizeF size;
};
List<Circle> circles;
public Window()
{
this.Text = "Line";
this.Size = SizeFromClientSize(new Size(640, 480));
pictureBox = new PictureBox();
pictureBox.Dock = DockStyle.Fill;
pictureBox.BackColor = Color.White;
pictureBox.Paint += new PaintEventHandler(pictureBox_Paint);
this.Controls.Add(pictureBox);
this.Load += new EventHandler(Window_Load);
this.Resize += new EventHandler(Window_Resize);
circles = new List<Circle>();
timer = new Timer();
timer.Interval = 15;
timer.Enabled = true;
timer.Tick += new EventHandler(timer_Tick);
}
private void pictureBox_Paint(object sender, PaintEventArgs e)
{
Graphics g = Graphics.FromImage(bmp);
g.Clear(Color.Black);
foreach (Circle c in circles)
{
g.DrawEllipse(Pens.White, new RectangleF(c.position, c.size));
}
pictureBox.Image = bmp;
}
private void timer_Tick(object sender, EventArgs e)
{
Circle c;
Console.WriteLine("Works");
for (int i = 0; i < circles.Count; i++)
{
c = circles[i];
c.size.Width = (c.size.Width > 200) ? 100 : c.size.Width + 1;
circles[i] = c;
}
pictureBox.Invalidate();
}
private void Window_Load(object sender, EventArgs e)
{
bmp = new Bitmap(this.Width, this.Height);
circles.Add(new Circle());
Circle c = circles[0];
c.position = new PointF(100, 100);
c.size = new SizeF(100, 100);
circles[0] = c;
}
private void Window_Resize(object sender, EventArgs e)
{
bmp = new Bitmap(this.Width, this.Height);
pictureBox.Invalidate();
}
}
}
Same code worked fine in Xamarin.
1) in timer_Tick remove line: pictureBox.Invalidate();
2) cut code from pictureBox_Paint and paste at the end of timer_Tick
3) fix variable name collision c
I am stuck at trying to call a procedure and use some parameters in a new thread in C#. There is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace Random_colored_rectangles
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Thread th;
Random rand;
System.Drawing.Color[] colors = new System.Drawing.Color[5] {Color.Orange, Color.Red, Color.Pink, Color.Black, Color.Gold };
private void DrawColor(Color color)
{
for (int i = 0; i < 100; i++)
{
DrawRectangle(color, 3 , rand.Next(0, this.Width), rand.Next(0, this.Height), 10, 10);
Thread.Sleep(100);
}
MessageBox.Show(color + " done");
}
private void DrawRectangle(Color barva, float width, int pos_x, int pos_y, int size_x, int size_y)
{
Pen myPen = new Pen(barva, width);
Graphics formGraphics;
formGraphics = plocha.CreateGraphics();
formGraphics.DrawRectangle(myPen, new Rectangle(pos_x, pos_y, size_x, size_y));
myPen.Dispose();
formGraphics.Dispose();
}
private void Form1_Load(object sender, EventArgs e)
{
rand = new Random();
}
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.R)
{
th = new Thread(DrawColor);
th.Name = Convert.ToString(threadCount);
threadList.Add(th);
threadCount = threadCount + 1;
th.Start(colors[rand.Next(0, colors.Length)]);
}
}
}
}
This code should (after pressing R) make 100 random colored rectangles (the color is chosen from an array of few colors). But, I am unable to make my thread start the procedure DrawColor with a parameter of the random color select.
Can you please help me?
You could do it by using a Task.
Color theColorToPass = someColor;
Task.Factory.StartNew(color => {
DrawColor(color);
}, theColorToPass);
You could aswell access the array directly from within the Task though. I see no point in passing it to the Thread.
Using the advice of those more familiar with the do's and don'ts of C# (that is not me trying to sound mean or anything), I have devised a way to accomplish what you want without the need of CreateGraphics() or Thread.Sleep(). Unfortunately, this throws an OutOfMemoryException when it hits e.Graphics.DrawRectangle(penToUse, rectanglesToUse[0]);. What does that mean?
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace Colors
{
public partial class Form1 : Form
{
Timer timer = new Timer { Interval = 100 };
Random rand = new Random();
Color[] colors = new Color[5]
{
Color.Black,
Color.Blue,
Color.Green,
Color.Purple,
Color.Red
};
List<Pen> usedPens = new List<Pen>();
List<Rectangle> usedRectangles = new List<Rectangle>();
Pen penToUse;
List<Rectangle> rectanglesToUse = new List<Rectangle>();
public Form1()
{
InitializeComponent();
}
protected override void OnKeyPress(KeyPressEventArgs e)
{
if (e.KeyChar == (char)Keys.Enter)
{
penToUse = new Pen(GetRandomColor(), 3);
rectanglesToUse.Clear();
for (int i = 0; i < 100; i++)
rectanglesToUse.Add(GetRandomRectangle());
this.Refresh();
}
}
private Color GetRandomColor()
{
return colors[rand.Next(0, colors.Length)];
}
private Rectangle GetRandomRectangle()
{
return new Rectangle(rand.Next(0, Width), rand.Next(0, Height), 10, 10);
}
protected override void OnPaint(PaintEventArgs e)
{
for (int i = 0; i < usedRectangles.Count; i++)
e.Graphics.DrawRectangle(usedPens[i % 100], usedRectangles[i]);
timer.Tick += delegate
{
if (rectanglesToUse.Count > 0)
{
e.Graphics.DrawRectangle(penToUse, rectanglesToUse[0]);
usedRectangles.Add(rectanglesToUse[0]);
rectanglesToUse.RemoveAt(0);
}
else
{
usedPens.Add(penToUse);
timer.Stop();
}
};
timer.Start();
}
}
}
I currently have an TChart where I want to introduce a draggable horizontal line which changes the color of the points below the line. I have chosen to use ColorLine for this purpose but the line does not appear in the TChart. Am I using the right TChart tool for the job or am I missing something?
Below is the stripped down version of my current code.
public class testClass
{
private ColorLine line;
private double lineYVal = 5;
private TChart savedChart;
public testClass()
{
line = new Colorline();
line.AllowDrag = true;
line.Pen.Color = Color.Red;
line.EndDragLine += lineDragHandler;
}
public void foo(TChart chart) //chart is prepopulated with datapoints from 0->10
{
savedChart = chart;
//existing code which assigns colors
chart.Series[0].ColorRange(chart.Series[0].YValues, double.MinValue, lineYVal, Color.Red);
chart.Series[0].ColorRange(chart.Series[0].YValues, lineYVal, double.MaxValue, Color.Blue);
//my attempt to add a line
chart.Tools.Add(line);
line.Active = true;
line.Axis = chart.Axes.Left;
line.Value = lineYVal;
}
private void lineDragHandler(object sender)
{
lineYVal = line.Value;
savedChart.Tools.Clear(); //remove existing line from chart
foo(savedChart); //redo colors and re-add line
}
}
Code below works fine for me here. If your problem persists please send a Short, Self Contained, Correct (Compilable), Example project to reproduce the problem here. You can post your files at www.steema.net/upload.
using Steema.TeeChart;
using Steema.TeeChart.Styles;
using Steema.TeeChart.Tools;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
InitializeChart();
}
private void InitializeChart()
{
testClass();
//existing code which assigns colors
tChart1.Series.Add(new Steema.TeeChart.Styles.Bar()).FillSampleValues();
tChart1.Series[0].ColorRange(tChart1.Series[0].YValues, double.MinValue, lineYVal, Color.Red);
tChart1.Series[0].ColorRange(tChart1.Series[0].YValues, lineYVal, double.MaxValue, Color.Blue);
//my attempt to add a line
tChart1.Tools.Add(line);
line.Active = true;
line.Axis = tChart1.Axes.Left;
line.Value = lineYVal;
}
private ColorLine line;
private double lineYVal = 5;
private TChart savedChart;
public void testClass()
{
line = new ColorLine();
line.AllowDrag = true;
line.Pen.Color = Color.Red;
line.EndDragLine += lineDragHandler;
}
public void foo(TChart chart) //chart is prepopulated with datapoints from 0->10
{
savedChart = chart;
//existing code which assigns colors
chart.Series[0].ColorRange(chart.Series[0].YValues, double.MinValue, lineYVal, Color.Red);
chart.Series[0].ColorRange(chart.Series[0].YValues, lineYVal, double.MaxValue, Color.Blue);
//my attempt to add a line
chart.Tools.Add(line);
line.Active = true;
line.Axis = chart.Axes.Left;
line.Value = lineYVal;
}
private void lineDragHandler(object sender)
{
lineYVal = line.Value;
if (savedChart != null)
{
savedChart.Tools.Clear(); //remove existing line from chart
foo(savedChart); //redo colors and re-add line
}
else
{
foo(tChart1);
}
}
}
}
It turns out that while the line was being added correctly, the code I was using to display the chart was not updating the chart properly and was displaying a version of the chart from before it was passed into my highlight function.
I have a user control chart in my Form1 designer and this is the code to resize it:
private void graphChart1_MouseEnter(object sender, EventArgs e)
{
graphChart1.Size = new Size(600, 600);
}
When I move the mouse to the control area it's not resizing it make it bigger but deleting some other controls.
This is an image before I move the mouse over the control:
And this is an image when I moved the mouse over the control:
This is the code of the user control where the chart is:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Web;
using System.Windows.Forms.DataVisualization.Charting;
namespace GatherLinks
{
public partial class GraphChart : UserControl
{
public GraphChart()
{
InitializeComponent();
}
private double f(int i)
{
var f1 = 59894 - (8128 * i) + (262 * i * i) - (1.6 * i * i * i);
return f1;
}
private void GraphChart_Load(object sender, EventArgs e)
{
chart1.Series.Clear();
var series1 = new System.Windows.Forms.DataVisualization.Charting.Series
{
Name = "Series1",
Color = System.Drawing.Color.Green,
IsVisibleInLegend = false,
IsXValueIndexed = true,
ChartType = SeriesChartType.Line
};
this.chart1.Series.Add(series1);
for (int i = 0; i < 100; i++)
{
series1.Points.AddXY(i, f(i));
}
chart1.Invalidate();
}
}
}
EDIT:
I did this in the user control class code:
public void ChangeChartSize(int width, int height)
{
chart1.Size = new Size(width, height);
chart1.Invalidate();
}
I had to add chart1.Invalidate(); to make it to take effect but then it sized the chart it self inside the user control. The user control was not changed.
So in the Form1 mouse enter I also changing the graphChart1 the control size:
private void graphChart1_MouseEnter(object sender, EventArgs e)
{
graphChart1.ChangeChartSize(600, 600);
graphChart1.Size = new Size(600, 600);
}
The problem is that now it's taking a lot of time almost 20 seconds or so until it take effect when I'm moving the mouse over the control. If I will remove the second line:
graphChart1.Size = new Size(600, 600);
it will work fast but then it will change the chart only inside the control but it won't change the control size.
Tried also with invalidate:
private void graphChart1_MouseEnter(object sender, EventArgs e)
{
graphChart1.ChangeChartSize(600, 600);
graphChart1.Size = new Size(600, 600);
graphChart1.Invalidate();
}
But still very slow. Maybe I need to change the control it self size also in the user control class code and not in Form1 ?
The problem is that you are resizing the GraphicChart (your user control) but not the Chart itself. You could add the method in your GraphChart class in order to do that. This is the method that will change the chart size:
public void ChangeChartSize(int width, int height)
{
chart1.Size = new Size(width, height);
}
And in your mouse enter event handler you could call something like this:
void graphicChart1_MouseEnter(object sender, EventArgs e)
{
graphChart1.ChangeChartSize(600, 600);
}
With graphChart1.Size = you are resizing your container but not the chart within it.
The easiest work-around is probably to make chart1 public in the control and do graphChart1.chart1.Size = instead.
In the user control class code I did:
public void ChangeChartSize(int width, int height)
{
this.Size = new Size(width, height);
chart1.Size = new Size(width, height);
chart1.Invalidate();
}
In Form1 I did:
private void graphChart1_MouseEnter(object sender, EventArgs e)
{
graphChart1.ChangeChartSize(600, 600);
}
Working smooth.