Hello everyone,
I would like to ask for your help, guys. For some reasons, if i include the following lines in my paint event handler of my picture box, the GUI acts very weird (as if it cannot "draw" all the controls, some of them are invisible or the program acts as if there is no threading). The reason is because I include those lines of code. But what is the real reason behind it? Is it because Paint event handler tries to re-paint the controls all the time or what? -
void panelGraphDynamic_Paint(object sender, PaintEventArgs e)
-
{
-
Point yAxis_Start = new Point(5, 8);
-
Point yAxis_End = new Point(5, 185);
-
Point xAxis_Start = new Point(5, 185);
-
Point xAxis_End = new Point(310, 185);
-
-
graphDynamic = new My_Graph(
-
panelGraphDynamic,
-
yAxis_Start, yAxis_End,
-
xAxis_Start, xAxis_End,
-
2, 1,
-
107);
-
-
}
-
-
public My_Graph(
-
PictureBox panelGraphDynamic,
-
Point pointY_axis_Start, Point pointY_axis_End,
-
Point pointX_axis_Start, Point pointX_axis_End,
-
int axisBrushWidth, int graphBrushWidth,
-
int numberOfTrainingPairs)
-
{
-
panelGraphDynamic.Image = new Bitmap(panelGraphDynamic.Width, panelGraphDynamic.Height);
-
Image bmp = panelGraphDynamic.Image;
-
this.gfx = Graphics.FromImage(bmp);
-
this.solBrushAxis = new SolidBrush(Color.Black);
-
this.colorPenBlackAxis = new Pen(this.solBrushAxis, (float)(axisBrushWidth)); //brush
-
-
this.pointX_axis_Start = pointX_axis_Start;
-
this.pointX_axis_End = pointX_axis_End;
-
this.pointY_axis_Start = pointY_axis_Start;
-
this.pointY_axis_End = pointY_axis_End;
-
-
this.gfx.DrawLine(this.colorPenBlackAxis, this.pointY_axis_Start, this.pointY_axis_End); //Y axis
-
this.gfx.DrawLine(this.colorPenBlackAxis, this.pointX_axis_Start, this.pointX_axis_End); //X axis
-
-
panelGraphDynamic.Image = bmp;
-
}
-
Before I used a panel to draw in, but I've realized it is a better and smarter thing to draw on an image that would be put in the picture box later. Also, it would be easier to save my graph as a picturebox(bitmap).
Thanks in advance for the explanation.
I think you have a recursive loop going on.
Every time you paint, you make a new MyGraph
- graphDynamic = new My_Graph
Every time you make a new MyGraph you force the repaint event to fire
- panelGraphDynamic.Image = new Bitmap(panelGraphDynamic.Width, panelGraphDynamic.Height);
Every time you paint you make a graph which makes you paint which makes a graph which makes you paint which makes a graph which makes you paint which makes a graph which makes you paint...
77 6224
I think you have a recursive loop going on.
Every time you paint, you make a new MyGraph
- graphDynamic = new My_Graph
Every time you make a new MyGraph you force the repaint event to fire
- panelGraphDynamic.Image = new Bitmap(panelGraphDynamic.Width, panelGraphDynamic.Height);
Every time you paint you make a graph which makes you paint which makes a graph which makes you paint which makes a graph which makes you paint which makes a graph which makes you paint...
I see, then i will need to fix the second line you pointed out.
I don't mean to sound disheartening, but I think you will need to do more than that.
May I point out that your Paint handler doesn't actually paint anything, and that your MyGraph doesn't actually return a graphic?
I have no idea what your total project is, or how these fit into the scheme of things... but I'm going to bet that you don't need to write a custom Paint handler for the Picturebox if you are already using a method to build the image.
Have your MyGraph method return the finished image (to whatever method called it), then set that returned image as the PictureBox.Image
Well, the thing is I was thinking to instantiate MyGraph class in the Load event handler of the main form (main gui). It would solve the problem, i assume.
MyGraphh class has my own - public void DrawGraph(double var_Yaxis)
that would draw a line on Y axis correspond to the X axis' value (based on counter++, or probably I will add another method that would take 2 args, X and Y vars). I know there are certain libraries for graphs and charts over there, but I wanted to build my project using my own code.
Anyway, that class is responsible for drawing a graph on my previously used panel, that's it.
As example: - void trainingANN_instance_BadFactsForGraphSynch(double variable)
-
{
-
if (this.InvokeRequired)
-
{
-
this.Invoke(new DelegateToCrossThread_Double (trainingANN_instance_BadFactsForGraphSynch), new object[] {variable});
-
}
-
else
-
{
-
graphDynamic.DrawGraph(variable);
-
this.tboxGraphEpoch.Text = this.tbEpoch.Text;
-
this.tboxGraphError.Text = "" + variable;
-
}
-
}
thats why i will use counter++, since it will directly reflect each invoke.
Anyways, my instantiation would draw X,Y axis and certain labels on a picturebox. Hope I made myself clear, if you need something else, pls let me know.
P.S. nice seeing some people trying to help a newbie. I really appreciate your input :)
but I wanted to build my project using my own code.
Praise the cyber dieties! We have an actual coder amongst us. Its so refreshing to hear someone say that want to write their own code and not just copy/paste a solution that someone else gives them. You have my full attention and support.
Help me get a better understanding of what you are doing.
Are you making a new component, inherited from Picturebox? Or are these classes separate from the Picturebox yet still trying to manipulate it?
I'm just thinking that the most reusable form of all this work might be to make a custom control, derived from Picturebox.
You send it an image along with some parameters, then update a method you give it like... UpdateGraph() or something similar.
Put the burden of the graphing inside your new GraphingPictureBox control. This leaves your application free to do it's part, which is just sending values, just like you do with any other control out of the Toolbox. - myGraphingPictureBox.Image = aaa;
-
myGraphingPictureBox.Caption = "Sales Figures";
-
myGraphingPictureBox.Xscale = xxxx;
-
myGraphingPictureBox.Yscale = yyyy;
-
myGraphingPictureBox.UpdateGraph();
Thanks :)))
I am trying to get my hands dirty with AI concepts and certain alogrithms. For now, my project is artificial neural network. After that I would like to work on genetic algorithms. :)
I am almost done with this project, just minor brush ups, to optimize the code, make the GUI more user-friendlier and informative.
I am trying to manipulate a picturebox (better saying, its content) with another class and its methods. Before I've used a panel to draw in, but decided to swtich to a picBox, since it is much more efficient. Anyways, if i do like this, there are no problems: -
private void ANN_GUI_Load(object sender, EventArgs e)
-
{
-
-
Point yAxis_Start = new Point(5, 8);
-
Point yAxis_End = new Point(5, 185);
-
Point xAxis_Start = new Point(5, 185);
-
Point xAxis_End = new Point(310, 185);
-
-
graphDynamic = new My_Graph(
-
panelGraphDynamic,
-
yAxis_Start, yAxis_End,
-
xAxis_Start, xAxis_End,
-
2, 1,
-
107);
-
}
If I put that code in the paint event, as you pointed out, it would infinitely try to re-draw the component (nested paint).
this is my constructor of the graph class: - public My_Graph(
-
PictureBox panelGraphDynamic,
-
Point pointY_axis_Start, Point pointY_axis_End,
-
Point pointX_axis_Start, Point pointX_axis_End,
-
int axisBrushWidth, int graphBrushWidth,
-
int numberOfTrainingPairs)
-
{
-
panelGraphDynamic.Image = new Bitmap(panelGraphDynamic.Width, panelGraphDynamic.Height);
-
Image bmp = panelGraphDynamic.Image;
-
this.gfx = Graphics.FromImage(bmp);
-
this.solBrushAxis = new SolidBrush(Color.Black);
-
this.colorPenBlackAxis = new Pen(this.solBrushAxis, (float)(axisBrushWidth)); //brush
-
-
this.pointX_axis_Start = pointX_axis_Start;
-
this.pointX_axis_End = pointX_axis_End;
-
this.pointY_axis_Start = pointY_axis_Start;
-
this.pointY_axis_End = pointY_axis_End;
-
-
this.gfx.DrawLine(this.colorPenBlackAxis, this.pointY_axis_Start, this.pointY_axis_End); //Y axis
-
this.gfx.DrawLine(this.colorPenBlackAxis, this.pointX_axis_Start, this.pointX_axis_End); //X axis
-
-
panelGraphDynamic.Image = bmp;
-
/*
-
this.panelGraphDynamic = panelGraphDynamic; //control box for the graph
-
toSaveBMP = new Bitmap(panelGraphDynamic.Width, panelGraphDynamic.Height);
-
-
this.gfx = this.panelGraphDynamic.CreateGraphics(); //create graphics for the control
-
-
this.solBrushAxis = new SolidBrush(Color.Black);
-
this.colorPenBlackAxis = new Pen(this.solBrushAxis, (float)(axisBrushWidth)); //brush
-
-
this.pointX_axis_Start = pointX_axis_Start;
-
this.pointX_axis_End = pointX_axis_End;
-
this.pointY_axis_Start = pointY_axis_Start;
-
this.pointY_axis_End = pointY_axis_End;
-
-
this.gfx.DrawLine(this.colorPenBlackAxis, this.pointY_axis_Start, this.pointY_axis_End); //Y axis
-
this.gfx.DrawLine(this.colorPenBlackAxis, this.pointX_axis_Start, this.pointX_axis_End); //X axis
-
-
this.newFont = new Font("Courie New", 5);
-
this.pointY = new Point(1, 1);
-
this.gfx.DrawString("100%", newFont, solBrushAxis, pointY);
-
this.gfx.DrawString("0", newFont, solBrushAxis, this.pointX_axis_Start.X + 1, this.pointX_axis_End.Y-8);
-
this.gfx.DrawString("[epoch+]", newFont, solBrushAxis, this.pointX_axis_End.X - 30, this.pointX_axis_End.Y - 8);
-
-
this.solBrushGraph = new SolidBrush(Color.Green);
-
this.colorPenGraph = new Pen(solBrushGraph, (float)(graphBrushWidth));
-
this.offset = ((double)this.panelGraphDynamic.Height - 15) / numberOfTrainingPairs;
-
this.counter = 0;
-
toSave = new PictureBox();
-
*/
-
}
Basically, I would like to transfer "safely" from drawings on a panel to a picbox.
So, should I make instantiation in the Load method?
Basically, I would like to transfer "safely" from drawings on a panel to a picbox.
You aren't really drawing on either. You are drawing on a Graphic that comes from an image. That's it. It shouldn't matter what type of control is going to use it. The drawing is completely separate from the control type. Once you have a finished Image you can put it anyplace you like: In a picturebox, in a panel, save it to a jpg, whatever.
I'm not sure this needs to be an entire class when a method to make an image would be just fine. This might be a case of over complicating the plumbing.
Basic idea: The end result of this method should not be the direct manipulation of another control. It should only return the finished Image.
Get an image.
Manipulate the image.
Return the result.
Something close to this (But I don't have your project to test it in) - private void ANN_GUI_Load(object sender, EventArgs e)
-
{
-
-
Point yAxis_Start = new Point(5, 8);
-
Point yAxis_End = new Point(5, 185);
-
Point xAxis_Start = new Point(5, 185);
-
Point xAxis_End = new Point(310, 185);
-
-
Image SourceImage = panelGraphDynamic.Image;
-
Image YogiBear = new My_Graph(
-
SourceImage,
-
yAxis_Start, yAxis_End,
-
xAxis_Start, xAxis_End,
-
2, 1,
-
107);
-
-
panelGraphDynamic.Image = YogiBear;
-
}
I've deleted the large comment block for clarity. -
-
// Notice this method now has no tight binding to any control.
-
// You can pass it an image you get from a control, or from someplace else
-
// It will make your graphed image and return it.
-
// From there, do you as you like: Post it in a picturebox, or save it to hard drive.
-
private Image My_Graph(
-
Image bmp,
-
Point pointY_axis_Start, Point pointY_axis_End,
-
Point pointX_axis_Start, Point pointX_axis_End,
-
int axisBrushWidth, int graphBrushWidth,
-
int numberOfTrainingPairs)
-
{
-
-
this.gfx = Graphics.FromImage(bmp);// bmp was passed in directly as a parameter
-
this.solBrushAxis = new SolidBrush(Color.Black);
-
this.colorPenBlackAxis = new Pen(this.solBrushAxis, (float)(axisBrushWidth)); //brush
-
-
this.pointX_axis_Start = pointX_axis_Start;
-
this.pointX_axis_End = pointX_axis_End;
-
this.pointY_axis_Start = pointY_axis_Start;
-
this.pointY_axis_End = pointY_axis_End;
-
-
this.gfx.DrawLine(this.colorPenBlackAxis, this.pointY_axis_Start, this.pointY_axis_End); //Y axis
-
this.gfx.DrawLine(this.colorPenBlackAxis, this.pointX_axis_Start, this.pointX_axis_End); //X axis
-
-
return bmp;
-
}
I see, what if you change
Image SourceImage = panelGraphDynamic.Image;
with instantiating a new image inside the graph class, instead of passing it as an argument?
P.S. Well, i see what you did there, actually it would be the same thing, either I pass the control to work on, or the image itself....
P.S.S. Someone once told me that DrawLine is not that fast, is it true? Are there any other functions?
---
Thanks mate
Then you tightly bind the method to the panelGraphDynamic control. You can no longer use the method for any other purpose. The method is constrained to a single input source.
If you pass it in as an argument, you could keep the panel showing one thing, while you calculate the NEXT image in ADVANCE, then quickly swap them out.
Or you could loop it using a month's worth of source images, storing the results in a List<Image>... then display the entire month in rapid succession with no hang up from calculating BETWEEN displays - basically showing a suedo animation of progression.
Or pass in a completed image back to the same method with a different pen color and numeric values, so you create a green graph and a blue graph on the same background image for comparison.
If you output 10 different images to a FlowLayoutPanel then you can scroll through them all, side-by-side.
The thing is, My_Graph is a constructor, and i cannot return an image.
Also, my DrawGraph method has a condition, when appropriate counter reaches, it will Refresh() a control, in case i'd need to draw some long graphs, so it wont go overboard.
Also, I don't think
If you pass it in as an argument, you could keep the panel showing one thing, while you calculate the NEXT image in ADVANCE, then quickly swap them out.
would work in my case. I do not have other images. A method would send a large amount of X,Y coordinates every second, so graph would just draw those. So, if you do not mean the same thing, then i won't have other pictures.
However, it is a good consideration, need to think about it.
This
r you could loop it using a month's worth of source images, storing the results in a List<Image>... then display the entire month in rapid succession with no hang up from calculating BETWEEN displays - basically showing a suedo animation of progression.
is a very good thing, its like you are reading my mind. I was thinking to display (after previously mentioned Refresh procedure) a window form with all the "refreshed" graphs. :) Good thinking.
Even
Or pass in a completed image back to the same method with a different pen color and numeric values, so you create a green graph and a blue graph on the same background image for comparison.
was my idea, but i faced a problem with scaling. 1 graph would be scaled from 100 to 0, the other from 1 to 0...but might use something else.
he thing is, My_Graph is a constructor, and i cannot return an image.
That's what I meant when I said that it being a class of itself was probably overboard, when it could probably be more useful as a method.
I am a bit lost :(
Should I add instantiation to the main form Load event handler or re-code my graph class and re-implement in different way?
On load - Point yAxis_Start = new Point(5, 8);
-
Point yAxis_End = new Point(5, 185);
-
Point xAxis_Start = new Point(5, 185);
-
Point xAxis_End = new Point(310, 185);
-
-
graphDynamic = new My_Graph();
-
Image source = panelGraphDynamic.Image;
-
Image res = graphDynamic.DrawAxis(source, yAxis_Start, yAxis_End, xAxis_Start, xAxis_End, 2, 3, 107);
Graph class - public My_Graph()
-
{
-
-
}
-
-
public Image DrawAxis(
-
Image bmp,
-
Point pointY_axis_Start, Point pointY_axis_End,
-
Point pointX_axis_Start, Point pointX_axis_End,
-
int axisBrushWidth, int graphBrushWidth,
-
int numberOfTrainingPairs)
-
{
-
-
this.gfx = Graphics.FromImage(bmp);// bmp was passed in directly as a parameter
-
this.solBrushAxis = new SolidBrush(Color.Black);
-
this.colorPenBlackAxis = new Pen(this.solBrushAxis, (float)(axisBrushWidth)); //brush
-
-
this.pointX_axis_Start = pointX_axis_Start;
-
this.pointX_axis_End = pointX_axis_End;
-
this.pointY_axis_Start = pointY_axis_Start;
-
this.pointY_axis_End = pointY_axis_End;
-
-
this.gfx.DrawLine(this.colorPenBlackAxis, this.pointY_axis_Start, this.pointY_axis_End); //Y axis
-
this.gfx.DrawLine(this.colorPenBlackAxis, this.pointX_axis_Start, this.pointX_axis_End); //X axis
-
-
return bmp;
-
}
Error: Value cannot be null. Parameter name: image;
this line this.gfx = Graphics.FromImage(bmp);
Now it seems OK, however, the text labels are bold, why is that? -
public Image DrawAxis(
-
Image bmp,PictureBox picbox,
-
Point pointY_axis_Start, Point pointY_axis_End,
-
Point pointX_axis_Start, Point pointX_axis_End,
-
int axisBrushWidth, int graphBrushWidth,
-
int numberOfTrainingPairs)
-
{
-
bmp = new Bitmap(picbox.Width, picbox.Height);
-
this.gfx = Graphics.FromImage(bmp);// bmp was passed in directly as a parameter
-
this.solBrushAxis = new SolidBrush(Color.Black);
-
this.colorPenBlackAxis = new Pen(this.solBrushAxis, (float)(axisBrushWidth)); //brush
-
-
this.pointX_axis_Start = pointX_axis_Start;
-
this.pointX_axis_End = pointX_axis_End;
-
this.pointY_axis_Start = pointY_axis_Start;
-
this.pointY_axis_End = pointY_axis_End;
-
-
this.gfx.DrawLine(this.colorPenBlackAxis, this.pointY_axis_Start, this.pointY_axis_End); //Y axis
-
this.gfx.DrawLine(this.colorPenBlackAxis, this.pointX_axis_Start, this.pointX_axis_End); //X axis
-
-
Font newFont = new Font("Courie New", 5); //font for the label
-
Point pointOfLabel = new Point(1, 1); //point of the label
-
this.gfx.DrawString("100%", newFont, solBrushAxis, pointOfLabel); //string drawing
-
this.gfx.DrawString("0", newFont, solBrushAxis, this.pointX_axis_Start.X + 1, this.pointX_axis_End.Y - 8); //string drawing
-
this.gfx.DrawString("[counter]", newFont, solBrushAxis, this.pointX_axis_End.X - 30, this.pointX_axis_End.Y - 8); //string drawing
-
-
return bmp;
-
}
My "beta" graph drawing function: - public void DrawGraph(double var_Yaxis)
-
{
-
counter++;
-
-
-
float x2 = (float)(pointY_axis_Start.X + counter);//incrementing X
-
float y2 = (float) var_Yaxis; //not finished
-
-
gfx.DrawLine(colorPenGraph, tempX, tempY, x2, y2); //actual graph drawing
-
-
//not finished
-
panelGraphDynamic.Image = bmp;
-
}
I have a feeling that this is .Image = bmp is not very efficient, it would slow my program down. Am I correct? Also, I would need to reset the graph, so only the axis would be left. When I used a panel, I had to Refresh it, and that's it.
Hm...am I on the right track? :) -
private Point Xaxis_Start;
-
private Point Xaxis_End;
-
private Point Yaxis_Start;
-
private Point Yaxis_End;
-
private PictureBox panelGraphDynamic; //panel for graph
-
private Image bmp;
-
private Color ColorOfAxis;
-
-
private int width;
-
private int height;
-
-
public Point X_StartPoint
-
{
-
get { return this.Xaxis_Start; }
-
set { this.Xaxis_Start = value; }
-
}
-
-
public Point X_EndPoint
-
{
-
get { return this.Xaxis_End; }
-
set { this.Xaxis_End = value; }
-
}
-
-
public Point Y_StartPoint
-
{
-
get { return this.Yaxis_Start; }
-
set { this.Yaxis_Start = value; }
-
}
-
-
public Point Y_EndPoint
-
{
-
get { return this.Yaxis_End; }
-
set { this.Yaxis_End = value; }
-
}
-
-
public ANN_Graph(int width, int height)
-
{
-
this.width = width;
-
this.height = height;
-
-
this.bmp = new Bitmap(width, height);
-
}
-
public PictureBox DrawingIm
-
{
-
get { return this.panelGraphDynamic; }
-
set { this.panelGraphDynamic = value; }
-
}
-
-
public Color AxisColor
-
{
-
get { return this.ColorOfAxis; }
-
set { this.ColorOfAxis = value; }
-
}
-
-
public void DrawAxis()
-
{
-
panelGraphDynamic.Image = new Bitmap(width, height);
-
this.gfx = Graphics.FromImage(bmp);
-
this.solBrushAxis = new SolidBrush(AxisColor);
-
this.colorPenBlackAxis = new Pen(this.solBrushAxis, (float)(2)); //brush
-
-
this.gfx.DrawLine(this.colorPenBlackAxis, this.Yaxis_Start, this.Yaxis_End); //Y axis
-
this.gfx.DrawLine(this.colorPenBlackAxis, this.Xaxis_Start, this.Xaxis_End); //X axis
-
-
panelGraphDynamic.Image = bmp;
-
-
-
-
}
-
Now it seems OK, however, the text labels are bold, why is that?
That is usually a sign of drawing the text twice. I'll bet if you put in a breakpoint and walk through the code line-by-line you'll find you have a loop in there someplace.
I am a bit lost :(
Should I add instantiation to the main form Load event handler or re-code my graph class and re-implement in different way?
Best I can do is tell you how I would have done it, which I did. I would not have this as a class, but as a method in a class. I'm not trying to be difficult, its just that I am looking into your application from the outside through a very small peep-hole. I see such a small part of your entire project that it makes it hard to advice on overall architecture.
Should I send you via email my entire project? but before its done, i wouldn't want an entire project be online :) After I am done, i will post the code :)
I'm not sure I'm following your terms here. A point has two values: X, Y - private Point Xaxis_Start;
-
private Point Xaxis_End;
-
private Point Yaxis_Start;
-
private Point Yaxis_End;
-
-
public Point Y_EndPoint
-
{
-
get { return this.Yaxis_End; }
-
set { this.Yaxis_End = value; }
-
}
So having an Xend and Xstart, Yend and Ystart doesn't make sense. 4 points would determine a rectangle, not a line. If you have a Point then you have a StartPoint and EndPoint. You then use StartPoint.X and StartPoint.Y
Might I suggest something like: - private point StartPoint = new Point(0,0);
-
private point EndPoint = new Point(50, 50);
Now you have proper points, and they have been initialized to some some default value so you don't risk "null value" errors -
this.pointX_axis_Start = pointX_axis_Start;
-
this.pointX_axis_End = pointX_axis_End;
-
this.pointY_axis_Start = pointY_axis_Start;
-
this.pointY_axis_End = pointY_axis_End;
Setting all four values equal to themselves. What is this supposed to accomplish?
Point X start would determine from where the X axis would be drawn. point X end would determine where the drawing ends. The same applies for Y axis. -
1. this.pointX_axis_Start = pointX_axis_Start;
-
2. this.pointX_axis_End = pointX_axis_End;
-
3. this.pointY_axis_Start = pointY_axis_Start;
-
4. this.pointY_axis_End = pointY_axis_End;
-
In this case nothing, I've changed my constructor, before it initialized the class variables. Check the updated code pls
Point X start would determine from where the X axis would be drawn. point X end would determine where the drawing ends. The same applies for Y axis.
So all of your PointX values have a Y of zero? Such as new Point (15, 0) ??
Why use a point then if it's on the axis and y is always zero?
No, its not that. - graphDynamic = new ANN_Graph(panelGraphDynamic.Width,panelGraphDynamic.Height);
-
graphDynamic.X_StartPoint = new Point(5, 185);
-
graphDynamic.X_EndPoint = new Point(310, 185);
-
graphDynamic.Y_StartPoint = new Point(5, 8);
-
graphDynamic.Y_EndPoint = new Point(5, 185);
-
graphDynamic.AxisColor = Color.Black;
-
graphDynamic.DrawingIm = panelGraphDynamic;
-
graphDynamic.DrawAxis();
Also, I've checked about bold text. I inserted break points, it didn't re-draw.
Update
---
This - gfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
slightly made my text labels drawn by .DrawString method more clearer, but it is still not perfect. Any other solutions?
I don't see your text drawing code here.
Or at least I don't see anyplace you are assigning a font.
Here code I use every day for putting a label on a picture.
It measures the amount of space needed to draw the text, makes a box for the background, then draws the text on the box.
As you can see it takes a few clearly named parameters. - private static void AddLable(Color LableBack, Color LableFront, int Size, String szText, int X, int Y, PaintEventArgs e)
-
{
-
SolidBrush BackColor = new SolidBrush(LableBack);
-
SolidBrush FrontColor = new SolidBrush(LableFront);
-
Pen FramePen = new Pen(LableFront);
-
//FramePen.Width = 6.0F;
-
FramePen.Width = Size / 8;
-
try
-
{
-
using (Font myFont = new Font("Arial Black", Size))
-
{
-
SizeF oSize1 = e.Graphics.MeasureString(szText, myFont);
-
-
e.Graphics.FillRectangle(BackColor, X, Y, oSize1.Width, oSize1.Height);
-
e.Graphics.DrawRectangle(FramePen, X, Y, oSize1.Width, oSize1.Height);
-
e.Graphics.DrawString(szText, myFont, FrontColor, new PointF(X, Y));
-
}
-
}
-
finally
-
{
-
//grf.Dispose();
-
}
-
e.Graphics.Save();
-
BackColor.Dispose();
-
FrontColor.Dispose();
-
FramePen.Dispose();
-
}
-
And tends to get called from something like this - Rectangle RealEstate = new Rectangle(0, 0, myImage.Width, myImage.Height);
-
System.Drawing.Graphics myGraphic = System.Drawing.Graphics.FromImage(myImage);
-
PaintEventArgs e = new PaintEventArgs(myGraphic, RealEstate);
-
-
AddLable(LableBackColor, LableTextColor, LableSize, "Sample", 10, 10, e);
-
-
It was here:
#
# Font newFont = new Font("Courie New", 5); //font for the label
# Point pointOfLabel = new Point(1, 1); //point of the label
# this.gfx.DrawString("100%", newFont, solBrushAxis, pointOfLabel); //string drawing
Also, Is there a way to "reset" the image? When I used a panel, i just called Refresh method and Paint event took place, then my axis were drawn again and the graph continued. With this new approach with a picturebox, bitmap, I am kind of lost...
Thanks for your help.
.Refresh()
or
.Invalidate()
Also, Is there a way to "reset" the image?
I didn't know what you meant by 'reset'. Sorry.
Refresh and Invalidate aren't going to 'remove'. It is going to cause it to repaint.
If you want to remove it, then set the image to null.
Thanks for the hint :)
Anyways, almost finished it, but I am not 100% happy with it, I suspect it to be quite slow :( Attached it
I suspect it to be quite slow
- public void DrawAxis()
-
{
-
-
picBoxForGraph.Image = new Bitmap(width, height);
-
-
this.solBrushAxis = new SolidBrush(AxisColor);
-
this.colorPenBlackAxis = new Pen(this.solBrushAxis, (float)(2)); //brush
-
-
this.gfx.DrawLine(this.colorPenBlackAxis, this.Yaxis_Start, this.Yaxis_End); //Y axis
-
this.gfx.DrawLine(this.colorPenBlackAxis, this.Xaxis_Start, this.Xaxis_End); //X axis
-
gfx.DrawString("100%", newFont, solBrushAxis, pointOfLabel); //string drawing
-
this.gfx.DrawString("0", newFont, solBrushAxis, this.Xaxis_Start.X + 1, this.Xaxis_End.Y - 8); //string drawing
-
this.gfx.DrawString("[epoch+]", newFont, solBrushAxis, this.Xaxis_End.X - 30, this.Xaxis_End.Y - 8); //string drawing
-
bmp.Save("axis.bmp");
-
-
}
-
Do you really need to save a bitmap to hard drive every time you draw it? You might want that on it's own thread so it doesn't hold up your GUI
that was just a test call, sorry, forgot to remove, just to see if it saves, but yes, ur right. Also, ive noticed that if i add more arguments to Save, such as Format.bmp, it will not save the image, the image would be totally black.
How do you find my implementation? Any negative points? Any positive? I would like to improve my coding :) not just blindly copy-pasting :)
Please note that later on I would ad more methods, for now my graph is heavily dependent on events and so just one variable is passed.
my graph is heavily dependent on events
That's a good thing. I've done a couple article here on making programs event aware. Custom events - A practical guide Buiding an application - Part 1
How do you find my implementation? Any negative points? Any positive? I would like to improve my coding :)
Coding to me as a mix of science and art. Every artist and coder has their own style. Just because I find something odd, doesn't mean it's wrong or the next guy will find it odd. You have to find your own style that works for you.
The only points I could make, I have already made. - Using a Point for a single integer works, but is odd.
- I wouldn't tie my methods so tightly to the control (Panel/PictureBox)
Might want to pull out code (or comment out) that serves no purpose - this.width = width; // width = width ??
-
this.height = height; // height = height ??
You might want to get in the habit of giving your projects more meaningful names if you want to tell them apart
Please don't take these as negative or disparaging. I'm thrilled to see someone actually want to LEARN, and actually want to UNDERSTAND, and actually want to write their OWN CODE. With all that going for you, I don't see how you can help but to succeed.
* Using a Point for a single integer works, but is odd.
* I wouldn't tie my methods so tightly to the control (Panel/PictureBox)
1. At the point I was writing the code, that is the way I've done it, probably going to change it later on
2. Well, it is not that tightly bound to the control, however you'd need to draw somewhere. Would you implement it using a picturebox and then insert in any control? Or something else?
# this.width = width; // width = width ??
# this.height = height; // height = height ??
this.width // the variable named width, of this class
= width // = to the variable width of the method's parameters.
Thanks for your help
Would you implement it using a picturebox and then insert in any control? Or something else?
As mentioned earlier, I would make a control inherited from Picturebox to be a new GraphPictureBox control.
I'm just thinking that the most reusable form of all this work might be to make a custom control, derived from Picturebox.
You send it an image along with some parameters, then update a method you give it like... UpdateGraph() or something similar.
Put the burden of the graphing inside your new GraphingPictureBox control. This leaves your application free to do it's part, which is just sending values, just like you do with any other control out of the Toolbox.
I was thinking of how to secure that my properties are set before the actual drawing takes place, in order to eliminate possible run-time errors...
With conditions or some default settings?
Default settings at launch, and range checking every time a method is run is always a good idea.
I started doing GraphBox : PictureBox, want to experiment with that idea :)
My constructor would contain - graphicInstanct.DrawLine(parameters)
, however, I cannot access the ones that are assigned thru the designer mode, meaning that if i try to assign a starting point, like DrawLine("test",this.pointX, blah-blah); logically, since it is a constructor, it would pass NULL, however, in my designer, the value of pointX would be different (lets say (5,10)). How should I synchronize them? Any hint here pls?
You lost me. You can't pass an integer to your constructor? Why not? Are you getting an exception? Did you make a constructor that takes the parameters you are trying to pass
however, I cannot access the ones that are assigned thru the designer mode, meaning that if i try to assign a starting point, like DrawLine("test",this.pointX, blah-blah); logically, since it is a constructor,
This is all confused... Are you talking about the constructor, or are you talking about the method DrawLine?
I think you need to show more of the code you are trying. Let's see the constructor your have created and the code being use to call it.
small demo (beta) -
public GraphBox()
-
{
-
this.BorderStyle = BorderStyle.Fixed3D;
-
-
this.bmp = new Bitmap(this.Width, this.Height);
-
this.gfx = Graphics.FromImage(bmp);
-
-
this.Image = new Bitmap(this.Width, this.Height);
-
-
this.solBrushAxis = new SolidBrush(Color.Black);
-
-
this.colorPenBlackAxis = new Pen(this.solBrushAxis, (float)(2)); //brush
-
this.fontForLabels = new Font("Courie New", 6, FontStyle.Regular); //font for the label
-
this.pointOfLabel = new Point(1, 1); //point of the label
-
-
Point yAxis_Start = new Point(5, 8);
-
Point yAxis_End = new Point(5, 185);
-
Point xAxis_Start = new Point(5, 185);
-
Point xAxis_End = new Point(310, 185);
-
-
this.gfx.DrawLine(this.colorPenBlackAxis, yAxis_Start, yAxis_End); //Y axis
-
this.gfx.DrawLine(this.colorPenBlackAxis, xAxis_Start, xAxis_End); //X axis
-
this.gfx.DrawString("100%", this.fontForLabels, this.solBrushAxis, this.pointOfLabel); //string drawing
-
-
this.Image = bmp;
-
}
-
And it is dragged in Designer mode -
this.graphBox1.AxisColor = System.Drawing.Color.Black; //originally it was Color.Empty
-
this.graphBox1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
-
this.graphBox1.GraphColor = System.Drawing.Color.Green; //Color.Epmty originally
-
this.graphBox1.Location = new System.Drawing.Point(258, 88);
-
this.graphBox1.Max_On_Yaxis = 0;
-
this.graphBox1.Name = "graphBox1";
-
this.graphBox1.Size = new System.Drawing.Size(321, 203);
-
this.graphBox1.TabIndex = 0;
-
this.graphBox1.TabStop = false;
-
this.graphBox1.X_EndPoint = new System.Drawing.Point(310, 185); //all of these were 0 originally
-
this.graphBox1.X_StartPoint = new System.Drawing.Point(5, 185);
-
this.graphBox1.Y_EndPoint = new System.Drawing.Point(5, 185);
-
this.graphBox1.Y_StartPoint = new System.Drawing.Point(5, 8);
-
Your constructor is missing
InitializeComponent();
And it is dragged in Designer mode -
this.graphBox1.AxisColor = System.Drawing.Color.Black; //originally it was Color.Empty
-
this.graphBox1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
-
this.graphBox1.GraphColor = System.Drawing.Color.Green; //Color.Epmty originally
-
this.graphBox1.Location = new System.Drawing.Point(258, 88);
-
this.graphBox1.Max_On_Yaxis = 0;
-
this.graphBox1.Name = "graphBox1";
-
this.graphBox1.Size = new System.Drawing.Size(321, 203);
-
this.graphBox1.TabIndex = 0;
-
this.graphBox1.TabStop = false;
-
this.graphBox1.X_EndPoint = new System.Drawing.Point(310, 185); //all of these were 0 originally
-
this.graphBox1.X_StartPoint = new System.Drawing.Point(5, 185);
-
this.graphBox1.Y_EndPoint = new System.Drawing.Point(5, 185);
-
this.graphBox1.Y_StartPoint = new System.Drawing.Point(5, 8);
What do you mean "And it is dragged in Designer mode"? These are properties of your control, right? When you drag an instance of this control onto a form, you should be able to change these in the Properties pallet.
I see, forgot about that. So basically I will need to make it as other window.form controls generated by the system automatically (by the designer)?
I started doing GraphBox : PictureBox, want to experiment with that idea :)
I thought you were trying to make a custom control inherited from PictureBox. Do I misunderstand?
As such it would be a control, just like a PictureBox that you would drag on your form, then give it values and implement it's methods. Only as a custom control you would have custom methods so it does what you want it to do.
Am I missing your goal?
I see, no, you are not missing anything. It's just that I have a little of experience with creating my own custom controls. The problem now is that I have problems with DrawLine method, it does not draw lines with the length I want. I need to debug and see what is the problem.
Thanks again.
Weird thing. I cannot understand why the line does not become longer :-/
Something to do with bitmap pixels or what?
---
I think I've found a problem...I will post it later on
-
private void InitializeComponent()
-
{
-
this.bmp = new Bitmap(this.Width, this.Height);
-
shows 100x50, while -
this.graphBox1.Size = new System.Drawing.Size(174, 127);
-
Is there a way to fix it (apart from instantiating in another method) ?
Sign in to post your reply or Sign up for a free account.
Similar topics
by: Zach |
last post by:
This is all on linux using jdk1.3. My application is written in AWT,
no swing.
The application requires running it on the host machine and tunneling
the GUI back to a client. I've been doing...
|
by: DraguVaso |
last post by:
Hi,
In the override of the Paint-method of a DataGridTextBoxColumn I want to
show an image with BitBlt, to see what I can gain there on performance.
The problem is: It doesn't show me the image...
|
by: Franck |
last post by:
Hello,
Sorry if that question has already been raised...
I'm looking for the exact equivalent of Java paint(Graphics g) method in c#
in order to paint a specific component and all its children...
|
by: Benny Raymond |
last post by:
I'm trying to adjust the length of the strings being drawn, as well as
some effects depending on what item is actually being drawn. I tried
doing the following, but the paint event never runs:
...
|
by: Stig |
last post by:
I would like to output the sequence of method calls from a running c#
applcaition, but I don't want to add Debug.trace calls at the entry and
exit points in each an every methods.
Does there...
|
by: 63q2o4i02 |
last post by:
Hi, I'm interested in using python to start writing a CAD program for
electrical design. I just got done reading Steven Rubin's book, I've
used "real" EDA tools, and I have an MSEE, so I know what...
|
by: smnoff |
last post by:
I have searched the internet for malloc and dynamic malloc; however, I still
don't know or readily see what is general way to allocate memory to char *
variable that I want to assign the substring...
|
by: Matt Bitten |
last post by:
I've got a wxPython program that needs to do some drawing on a DC on a
regular basis, whether or not a paint event happens. I know how to
make a ClientDC to do the drawing in, and I know what...
|
by: Leo Lee |
last post by:
Hi, I think I have already solved this problem while I am digging into the
installation sources.
I found this:
C:\Python25\Lib\site-packages\py2exe\samples\singlefile\gui\setup.py
# Requires...
|
by: lilyumestar |
last post by:
I have project I have to do for class. We have to write 4 different .java files.
Project2.java
HouseGUI.java
House.java
HouseSorting.java
I already finish House.java and I need to work on...
|
by: Charles Arthur |
last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
|
by: emmanuelkatto |
last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud.
Please let me know.
Thanks!
Emmanuel
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
by: Sonnysonu |
last post by:
This is the data of csv file
1 2 3
1 2 3
1 2 3
1 2 3
2 3
2 3
3
the lengths should be different i have to store the data by column-wise with in the specific length.
suppose the i have to...
|
by: Hystou |
last post by:
There are some requirements for setting up RAID:
1. The motherboard and BIOS support RAID configuration.
2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
|
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
|
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
| |