473,405 Members | 2,445 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,405 software developers and data experts.

My Method on Paint drastically effects my program GUI's performance

EARNEST
128 100+
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?
Expand|Select|Wrap|Line Numbers
  1.         void panelGraphDynamic_Paint(object sender, PaintEventArgs e)
  2.         {
  3.             Point yAxis_Start = new Point(5, 8);
  4.             Point yAxis_End = new Point(5, 185);
  5.             Point xAxis_Start = new Point(5, 185);
  6.             Point xAxis_End = new Point(310, 185);
  7.  
  8.             graphDynamic = new My_Graph(
  9.                 panelGraphDynamic, 
  10.                 yAxis_Start, yAxis_End,
  11.                 xAxis_Start, xAxis_End,
  12.                 2, 1,
  13.                 107);
  14.  
  15.         }
  16.  
Expand|Select|Wrap|Line Numbers
  1.         public My_Graph(
  2.             PictureBox panelGraphDynamic, 
  3.             Point pointY_axis_Start, Point pointY_axis_End, 
  4.             Point pointX_axis_Start, Point pointX_axis_End, 
  5.             int axisBrushWidth, int graphBrushWidth,
  6.             int numberOfTrainingPairs)
  7.         {
  8.             panelGraphDynamic.Image = new Bitmap(panelGraphDynamic.Width, panelGraphDynamic.Height);
  9.             Image bmp = panelGraphDynamic.Image;
  10.             this.gfx = Graphics.FromImage(bmp);
  11.             this.solBrushAxis = new SolidBrush(Color.Black);
  12.             this.colorPenBlackAxis = new Pen(this.solBrushAxis, (float)(axisBrushWidth)); //brush
  13.  
  14.             this.pointX_axis_Start = pointX_axis_Start;
  15.             this.pointX_axis_End = pointX_axis_End;
  16.             this.pointY_axis_Start = pointY_axis_Start;
  17.             this.pointY_axis_End = pointY_axis_End;
  18.  
  19.             this.gfx.DrawLine(this.colorPenBlackAxis, this.pointY_axis_Start, this.pointY_axis_End); //Y axis
  20.             this.gfx.DrawLine(this.colorPenBlackAxis, this.pointX_axis_Start, this.pointX_axis_End); //X axis
  21.  
  22.             panelGraphDynamic.Image = bmp;
  23. }
  24.  
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.
Feb 25 '10 #1

✓ answered by tlhintoq

I think you have a recursive loop going on.

Every time you paint, you make a new MyGraph
Expand|Select|Wrap|Line Numbers
  1. graphDynamic = new My_Graph
Every time you make a new MyGraph you force the repaint event to fire
Expand|Select|Wrap|Line Numbers
  1. 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
tlhintoq
3,525 Expert 2GB
I think you have a recursive loop going on.

Every time you paint, you make a new MyGraph
Expand|Select|Wrap|Line Numbers
  1. graphDynamic = new My_Graph
Every time you make a new MyGraph you force the repaint event to fire
Expand|Select|Wrap|Line Numbers
  1. 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...
Feb 25 '10 #2
EARNEST
128 100+
I see, then i will need to fix the second line you pointed out.
Feb 25 '10 #3
tlhintoq
3,525 Expert 2GB
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
Feb 25 '10 #4
EARNEST
128 100+
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
Expand|Select|Wrap|Line Numbers
  1.  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:
Expand|Select|Wrap|Line Numbers
  1.         void trainingANN_instance_BadFactsForGraphSynch(double variable)
  2.         {
  3.             if (this.InvokeRequired)
  4.             {
  5.                 this.Invoke(new DelegateToCrossThread_Double (trainingANN_instance_BadFactsForGraphSynch), new object[] {variable});
  6.             }
  7.             else
  8.             {
  9.                 graphDynamic.DrawGraph(variable);
  10.                 this.tboxGraphEpoch.Text = this.tbEpoch.Text;
  11.                 this.tboxGraphError.Text = "" + variable;
  12.             }
  13.         }
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 :)
Feb 25 '10 #5
tlhintoq
3,525 Expert 2GB
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?
Feb 25 '10 #6
tlhintoq
3,525 Expert 2GB
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.

Expand|Select|Wrap|Line Numbers
  1. myGraphingPictureBox.Image =   aaa;
  2. myGraphingPictureBox.Caption =  "Sales Figures";
  3. myGraphingPictureBox.Xscale = xxxx;
  4. myGraphingPictureBox.Yscale = yyyy;
  5. myGraphingPictureBox.UpdateGraph();
Feb 25 '10 #7
EARNEST
128 100+
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:

Expand|Select|Wrap|Line Numbers
  1.         private void ANN_GUI_Load(object sender, EventArgs e)
  2.         {
  3.  
  4.             Point yAxis_Start = new Point(5, 8);
  5.             Point yAxis_End = new Point(5, 185);
  6.             Point xAxis_Start = new Point(5, 185);
  7.             Point xAxis_End = new Point(310, 185);
  8.  
  9.             graphDynamic = new My_Graph(
  10.                 panelGraphDynamic,
  11.                 yAxis_Start, yAxis_End,
  12.                 xAxis_Start, xAxis_End,
  13.                 2, 1,
  14.                 107);
  15.         }
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:
Expand|Select|Wrap|Line Numbers
  1.         public My_Graph(
  2.             PictureBox panelGraphDynamic, 
  3.             Point pointY_axis_Start, Point pointY_axis_End, 
  4.             Point pointX_axis_Start, Point pointX_axis_End, 
  5.             int axisBrushWidth, int graphBrushWidth,
  6.             int numberOfTrainingPairs)
  7.         {
  8.             panelGraphDynamic.Image = new Bitmap(panelGraphDynamic.Width, panelGraphDynamic.Height);
  9.             Image bmp = panelGraphDynamic.Image;
  10.             this.gfx = Graphics.FromImage(bmp);
  11.             this.solBrushAxis = new SolidBrush(Color.Black);
  12.             this.colorPenBlackAxis = new Pen(this.solBrushAxis, (float)(axisBrushWidth)); //brush
  13.  
  14.             this.pointX_axis_Start = pointX_axis_Start;
  15.             this.pointX_axis_End = pointX_axis_End;
  16.             this.pointY_axis_Start = pointY_axis_Start;
  17.             this.pointY_axis_End = pointY_axis_End;
  18.  
  19.             this.gfx.DrawLine(this.colorPenBlackAxis, this.pointY_axis_Start, this.pointY_axis_End); //Y axis
  20.             this.gfx.DrawLine(this.colorPenBlackAxis, this.pointX_axis_Start, this.pointX_axis_End); //X axis
  21.  
  22.             panelGraphDynamic.Image = bmp;
  23.             /*
  24.             this.panelGraphDynamic = panelGraphDynamic; //control box for the graph
  25.             toSaveBMP = new Bitmap(panelGraphDynamic.Width, panelGraphDynamic.Height);
  26.  
  27.             this.gfx = this.panelGraphDynamic.CreateGraphics(); //create graphics for the control           
  28.  
  29.             this.solBrushAxis = new SolidBrush(Color.Black);
  30.             this.colorPenBlackAxis = new Pen(this.solBrushAxis, (float)(axisBrushWidth)); //brush
  31.  
  32.             this.pointX_axis_Start = pointX_axis_Start;
  33.             this.pointX_axis_End = pointX_axis_End;
  34.             this.pointY_axis_Start = pointY_axis_Start;
  35.             this.pointY_axis_End = pointY_axis_End;
  36.  
  37.             this.gfx.DrawLine(this.colorPenBlackAxis, this.pointY_axis_Start, this.pointY_axis_End); //Y axis
  38.             this.gfx.DrawLine(this.colorPenBlackAxis, this.pointX_axis_Start, this.pointX_axis_End); //X axis
  39.  
  40.             this.newFont = new Font("Courie New", 5);
  41.             this.pointY = new Point(1, 1);            
  42.             this.gfx.DrawString("100%", newFont, solBrushAxis, pointY);
  43.             this.gfx.DrawString("0", newFont, solBrushAxis, this.pointX_axis_Start.X + 1, this.pointX_axis_End.Y-8);
  44.             this.gfx.DrawString("[epoch+]", newFont, solBrushAxis, this.pointX_axis_End.X - 30, this.pointX_axis_End.Y - 8);
  45.  
  46.             this.solBrushGraph = new SolidBrush(Color.Green);
  47.             this.colorPenGraph = new Pen(solBrushGraph, (float)(graphBrushWidth));
  48.             this.offset = ((double)this.panelGraphDynamic.Height - 15) / numberOfTrainingPairs;
  49.             this.counter = 0;
  50.             toSave = new PictureBox();
  51.             */
  52.         }
Basically, I would like to transfer "safely" from drawings on a panel to a picbox.
Feb 25 '10 #8
EARNEST
128 100+
So, should I make instantiation in the Load method?
Feb 25 '10 #9
tlhintoq
3,525 Expert 2GB
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)
Expand|Select|Wrap|Line Numbers
  1. private void ANN_GUI_Load(object sender, EventArgs e)
  2.         {
  3.  
  4.             Point yAxis_Start = new Point(5, 8);
  5.             Point yAxis_End = new Point(5, 185);
  6.             Point xAxis_Start = new Point(5, 185);
  7.             Point xAxis_End = new Point(310, 185);
  8.  
  9.             Image SourceImage = panelGraphDynamic.Image;
  10.             Image YogiBear = new My_Graph(
  11.                 SourceImage,
  12.                 yAxis_Start, yAxis_End,
  13.                 xAxis_Start, xAxis_End,
  14.                 2, 1,
  15.                 107);
  16.  
  17.             panelGraphDynamic.Image = YogiBear;
  18.         }

I've deleted the large comment block for clarity.
Expand|Select|Wrap|Line Numbers
  1.  
  2. // Notice this method now has no tight binding to any control.
  3. // You can pass it an image you get from a control, or from someplace else
  4. // It will make your graphed image and return it.
  5. // From there, do you as you like: Post it in a picturebox, or save it to hard drive.
  6. private Image My_Graph(
  7.             Image bmp
  8.             Point pointY_axis_Start, Point pointY_axis_End, 
  9.             Point pointX_axis_Start, Point pointX_axis_End, 
  10.             int axisBrushWidth, int graphBrushWidth,
  11.             int numberOfTrainingPairs)
  12.         {
  13.  
  14.             this.gfx = Graphics.FromImage(bmp);// bmp was passed in directly as a parameter
  15.             this.solBrushAxis = new SolidBrush(Color.Black);
  16.             this.colorPenBlackAxis = new Pen(this.solBrushAxis, (float)(axisBrushWidth)); //brush
  17.  
  18.             this.pointX_axis_Start = pointX_axis_Start;
  19.             this.pointX_axis_End = pointX_axis_End;
  20.             this.pointY_axis_Start = pointY_axis_Start;
  21.             this.pointY_axis_End = pointY_axis_End;
  22.  
  23.             this.gfx.DrawLine(this.colorPenBlackAxis, this.pointY_axis_Start, this.pointY_axis_End); //Y axis
  24.             this.gfx.DrawLine(this.colorPenBlackAxis, this.pointX_axis_Start, this.pointX_axis_End); //X axis
  25.  
  26.             return bmp;
  27.         }
Feb 25 '10 #10
EARNEST
128 100+
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
Feb 25 '10 #11
tlhintoq
3,525 Expert 2GB
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.
Feb 25 '10 #12
EARNEST
128 100+
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.
Feb 25 '10 #13
EARNEST
128 100+
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.
Feb 25 '10 #14
tlhintoq
3,525 Expert 2GB
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.
Feb 26 '10 #15
EARNEST
128 100+
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?
Feb 26 '10 #16
EARNEST
128 100+
On load
Expand|Select|Wrap|Line Numbers
  1.            Point yAxis_Start = new Point(5, 8);
  2.             Point yAxis_End = new Point(5, 185);
  3.             Point xAxis_Start = new Point(5, 185);
  4.             Point xAxis_End = new Point(310, 185);
  5.  
  6.             graphDynamic = new My_Graph();
  7.             Image source = panelGraphDynamic.Image;
  8.             Image res = graphDynamic.DrawAxis(source, yAxis_Start, yAxis_End, xAxis_Start, xAxis_End, 2, 3, 107);
Graph class
Expand|Select|Wrap|Line Numbers
  1.         public My_Graph()
  2.         {
  3.  
  4.         }
  5.  
  6.         public Image DrawAxis(
  7.             Image bmp,
  8.             Point pointY_axis_Start, Point pointY_axis_End,
  9.             Point pointX_axis_Start, Point pointX_axis_End,
  10.             int axisBrushWidth, int graphBrushWidth,
  11.             int numberOfTrainingPairs)
  12.         {
  13.  
  14.             this.gfx = Graphics.FromImage(bmp);// bmp was passed in directly as a parameter
  15.             this.solBrushAxis = new SolidBrush(Color.Black);
  16.             this.colorPenBlackAxis = new Pen(this.solBrushAxis, (float)(axisBrushWidth)); //brush
  17.  
  18.             this.pointX_axis_Start = pointX_axis_Start;
  19.             this.pointX_axis_End = pointX_axis_End;
  20.             this.pointY_axis_Start = pointY_axis_Start;
  21.             this.pointY_axis_End = pointY_axis_End;
  22.  
  23.             this.gfx.DrawLine(this.colorPenBlackAxis, this.pointY_axis_Start, this.pointY_axis_End); //Y axis
  24.             this.gfx.DrawLine(this.colorPenBlackAxis, this.pointX_axis_Start, this.pointX_axis_End); //X axis
  25.  
  26.             return bmp;
  27.         }
Error: Value cannot be null. Parameter name: image;
this line this.gfx = Graphics.FromImage(bmp);
Feb 26 '10 #17
EARNEST
128 100+
Now it seems OK, however, the text labels are bold, why is that?
Expand|Select|Wrap|Line Numbers
  1.         public Image DrawAxis(
  2.             Image bmp,PictureBox picbox,
  3.             Point pointY_axis_Start, Point pointY_axis_End,
  4.             Point pointX_axis_Start, Point pointX_axis_End,
  5.             int axisBrushWidth, int graphBrushWidth,
  6.             int numberOfTrainingPairs)
  7.         {
  8.             bmp = new Bitmap(picbox.Width, picbox.Height);
  9.             this.gfx = Graphics.FromImage(bmp);// bmp was passed in directly as a parameter
  10.             this.solBrushAxis = new SolidBrush(Color.Black);
  11.             this.colorPenBlackAxis = new Pen(this.solBrushAxis, (float)(axisBrushWidth)); //brush
  12.  
  13.             this.pointX_axis_Start = pointX_axis_Start;
  14.             this.pointX_axis_End = pointX_axis_End;
  15.             this.pointY_axis_Start = pointY_axis_Start;
  16.             this.pointY_axis_End = pointY_axis_End;
  17.  
  18.             this.gfx.DrawLine(this.colorPenBlackAxis, this.pointY_axis_Start, this.pointY_axis_End); //Y axis
  19.             this.gfx.DrawLine(this.colorPenBlackAxis, this.pointX_axis_Start, this.pointX_axis_End); //X axis
  20.  
  21.             Font newFont = new Font("Courie New", 5); //font for the label
  22.             Point pointOfLabel = new Point(1, 1); //point of the label
  23.             this.gfx.DrawString("100%", newFont, solBrushAxis, pointOfLabel); //string drawing
  24.             this.gfx.DrawString("0", newFont, solBrushAxis, this.pointX_axis_Start.X + 1, this.pointX_axis_End.Y - 8); //string drawing
  25.             this.gfx.DrawString("[counter]", newFont, solBrushAxis, this.pointX_axis_End.X - 30, this.pointX_axis_End.Y - 8); //string drawing
  26.  
  27.             return bmp;
  28.         }
My "beta" graph drawing function:
Expand|Select|Wrap|Line Numbers
  1.         public void DrawGraph(double var_Yaxis)
  2.         {
  3.             counter++;
  4.  
  5.  
  6.             float x2 = (float)(pointY_axis_Start.X + counter);//incrementing X
  7.             float y2 = (float) var_Yaxis; //not finished
  8.  
  9.             gfx.DrawLine(colorPenGraph, tempX, tempY, x2, y2); //actual graph drawing
  10.  
  11.  //not finished
  12.             panelGraphDynamic.Image = bmp;
  13.         }
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.
Feb 26 '10 #18
EARNEST
128 100+
Hm...am I on the right track? :)
Expand|Select|Wrap|Line Numbers
  1.         private Point Xaxis_Start;
  2.         private Point Xaxis_End;
  3.         private Point Yaxis_Start;
  4.         private Point Yaxis_End;
  5.         private PictureBox panelGraphDynamic; //panel for graph
  6.         private Image bmp;
  7.         private Color ColorOfAxis;
  8.  
  9.         private int width;
  10.         private int height;
  11.  
  12.         public Point X_StartPoint
  13.         {
  14.             get { return this.Xaxis_Start; }
  15.             set { this.Xaxis_Start = value; }  
  16.         }
  17.  
  18.         public Point X_EndPoint
  19.         {
  20.             get { return this.Xaxis_End; }
  21.             set { this.Xaxis_End = value; }
  22.         }
  23.  
  24.         public Point Y_StartPoint
  25.         {
  26.             get { return this.Yaxis_Start; }
  27.             set { this.Yaxis_Start = value; }
  28.         }
  29.  
  30.         public Point Y_EndPoint
  31.         {
  32.             get { return this.Yaxis_End; }
  33.             set { this.Yaxis_End = value; }
  34.         }
  35.  
  36.         public ANN_Graph(int width, int height)
  37.         {
  38.             this.width = width;
  39.             this.height = height;
  40.  
  41.             this.bmp = new Bitmap(width, height);
  42.         }
  43.         public PictureBox DrawingIm
  44.         {
  45.             get { return this.panelGraphDynamic; }
  46.             set { this.panelGraphDynamic = value; }
  47.         }
  48.  
  49.         public Color AxisColor
  50.         {
  51.             get { return this.ColorOfAxis; }
  52.             set { this.ColorOfAxis = value; }
  53.         }
  54.  
  55.         public void DrawAxis()
  56.         {
  57.             panelGraphDynamic.Image = new Bitmap(width, height);
  58.             this.gfx = Graphics.FromImage(bmp);
  59.             this.solBrushAxis = new SolidBrush(AxisColor);
  60.             this.colorPenBlackAxis = new Pen(this.solBrushAxis, (float)(2)); //brush
  61.  
  62.             this.gfx.DrawLine(this.colorPenBlackAxis, this.Yaxis_Start, this.Yaxis_End); //Y axis
  63.             this.gfx.DrawLine(this.colorPenBlackAxis, this.Xaxis_Start, this.Xaxis_End); //X axis
  64.  
  65.             panelGraphDynamic.Image = bmp;
  66.  
  67.  
  68.  
  69.         }
  70.  
Feb 26 '10 #19
tlhintoq
3,525 Expert 2GB
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.
Feb 26 '10 #20
EARNEST
128 100+
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 :)
Feb 26 '10 #21
tlhintoq
3,525 Expert 2GB
I'm not sure I'm following your terms here. A point has two values: X, Y
Expand|Select|Wrap|Line Numbers
  1. private Point Xaxis_Start;
  2. private Point Xaxis_End;
  3. private Point Yaxis_Start;
  4. private Point Yaxis_End;
  5.  
  6. public Point Y_EndPoint
  7.         {
  8.             get { return this.Yaxis_End; }
  9.             set { this.Yaxis_End = value; }
  10.         }
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:

Expand|Select|Wrap|Line Numbers
  1. private point StartPoint = new Point(0,0);
  2. 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

Expand|Select|Wrap|Line Numbers
  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;
Setting all four values equal to themselves. What is this supposed to accomplish?
Feb 26 '10 #22
EARNEST
128 100+
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.
Expand|Select|Wrap|Line Numbers
  1.    1. this.pointX_axis_Start = pointX_axis_Start;
  2.    2. this.pointX_axis_End = pointX_axis_End;
  3.    3. this.pointY_axis_Start = pointY_axis_Start;
  4.    4. this.pointY_axis_End = pointY_axis_End;
  5.  
In this case nothing, I've changed my constructor, before it initialized the class variables. Check the updated code pls
Feb 26 '10 #23
tlhintoq
3,525 Expert 2GB
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?
Feb 26 '10 #24
EARNEST
128 100+
No, its not that.
Expand|Select|Wrap|Line Numbers
  1.             graphDynamic = new ANN_Graph(panelGraphDynamic.Width,panelGraphDynamic.Height);
  2.             graphDynamic.X_StartPoint = new Point(5, 185);
  3.             graphDynamic.X_EndPoint = new Point(310, 185);
  4.             graphDynamic.Y_StartPoint = new Point(5, 8);
  5.             graphDynamic.Y_EndPoint = new Point(5, 185);
  6.             graphDynamic.AxisColor = Color.Black;
  7.             graphDynamic.DrawingIm = panelGraphDynamic;
  8.             graphDynamic.DrawAxis();
Also, I've checked about bold text. I inserted break points, it didn't re-draw.
Feb 26 '10 #25
EARNEST
128 100+
Update
---
This
Expand|Select|Wrap|Line Numbers
  1. 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?
Feb 26 '10 #26
tlhintoq
3,525 Expert 2GB
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.
Expand|Select|Wrap|Line Numbers
  1. private static void AddLable(Color LableBack, Color LableFront, int Size, String szText, int X, int Y, PaintEventArgs e)
  2. {
  3.     SolidBrush BackColor = new SolidBrush(LableBack);
  4.     SolidBrush FrontColor = new SolidBrush(LableFront);
  5.     Pen FramePen = new Pen(LableFront);
  6.     //FramePen.Width = 6.0F;
  7.     FramePen.Width = Size / 8;
  8.     try
  9.     {
  10.         using (Font myFont = new Font("Arial Black", Size))
  11.         {
  12.             SizeF oSize1 = e.Graphics.MeasureString(szText, myFont);
  13.  
  14.             e.Graphics.FillRectangle(BackColor, X, Y, oSize1.Width, oSize1.Height);
  15.             e.Graphics.DrawRectangle(FramePen, X, Y, oSize1.Width, oSize1.Height);
  16.             e.Graphics.DrawString(szText, myFont, FrontColor, new PointF(X, Y));
  17.         }
  18.     }
  19.     finally
  20.     {
  21.         //grf.Dispose();
  22.     }
  23.     e.Graphics.Save();
  24.     BackColor.Dispose();
  25.     FrontColor.Dispose();
  26.     FramePen.Dispose();
  27. }
  28.  
And tends to get called from something like this
Expand|Select|Wrap|Line Numbers
  1. Rectangle RealEstate = new Rectangle(0, 0, myImage.Width, myImage.Height);
  2. System.Drawing.Graphics myGraphic = System.Drawing.Graphics.FromImage(myImage);
  3. PaintEventArgs e = new PaintEventArgs(myGraphic, RealEstate);
  4.  
  5. AddLable(LableBackColor, LableTextColor, LableSize, "Sample", 10, 10, e);
  6.  
  7.  
Feb 26 '10 #27
EARNEST
128 100+
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.
Feb 26 '10 #28
tlhintoq
3,525 Expert 2GB
.Refresh()

or

.Invalidate()
Feb 26 '10 #29
EARNEST
128 100+
Maybe I am doing something wrong, but Refresh doesnt work for me :(
http://img709.imageshack.us/i/26022010203039.png/
It doesn't remove the above graph, it keeps it there.
Feb 26 '10 #30
tlhintoq
3,525 Expert 2GB
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.
Feb 26 '10 #31
EARNEST
128 100+
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
Attached Files
File Type: txt ANN_Graph.cs.txt (6.1 KB, 268 views)
Feb 26 '10 #32
tlhintoq
3,525 Expert 2GB
I suspect it to be quite slow
Expand|Select|Wrap|Line Numbers
  1. public void DrawAxis()
  2.         {
  3.  
  4.             picBoxForGraph.Image = new Bitmap(width, height);
  5.  
  6.             this.solBrushAxis = new SolidBrush(AxisColor);
  7.             this.colorPenBlackAxis = new Pen(this.solBrushAxis, (float)(2)); //brush
  8.  
  9.             this.gfx.DrawLine(this.colorPenBlackAxis, this.Yaxis_Start, this.Yaxis_End); //Y axis
  10.             this.gfx.DrawLine(this.colorPenBlackAxis, this.Xaxis_Start, this.Xaxis_End); //X axis
  11.             gfx.DrawString("100%", newFont, solBrushAxis, pointOfLabel); //string drawing
  12.             this.gfx.DrawString("0", newFont, solBrushAxis, this.Xaxis_Start.X + 1, this.Xaxis_End.Y - 8); //string drawing
  13.             this.gfx.DrawString("[epoch+]", newFont, solBrushAxis, this.Xaxis_End.X - 30, this.Xaxis_End.Y - 8); //string drawing
  14.             bmp.Save("axis.bmp");
  15.  
  16.         }
  17.  
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
Feb 26 '10 #33
EARNEST
128 100+
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 :)
Feb 26 '10 #34
EARNEST
128 100+
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.
Feb 26 '10 #35
tlhintoq
3,525 Expert 2GB
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
Expand|Select|Wrap|Line Numbers
  1.            this.width = width; // width = width ??
  2. 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
Expand|Select|Wrap|Line Numbers
  1. namespace My_Project
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.
Feb 26 '10 #36
EARNEST
128 100+
* 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
Feb 27 '10 #37
tlhintoq
3,525 Expert 2GB
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.
Feb 27 '10 #38
EARNEST
128 100+
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?
Mar 1 '10 #39
tlhintoq
3,525 Expert 2GB
Default settings at launch, and range checking every time a method is run is always a good idea.
Mar 1 '10 #40
EARNEST
128 100+
I started doing GraphBox : PictureBox, want to experiment with that idea :)
My constructor would contain
Expand|Select|Wrap|Line Numbers
  1. 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?
Mar 1 '10 #41
tlhintoq
3,525 Expert 2GB
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.
Mar 1 '10 #42
EARNEST
128 100+
small demo (beta)
Expand|Select|Wrap|Line Numbers
  1.         public GraphBox()
  2.         {           
  3.             this.BorderStyle = BorderStyle.Fixed3D;
  4.  
  5.             this.bmp = new Bitmap(this.Width, this.Height);
  6.             this.gfx = Graphics.FromImage(bmp);
  7.  
  8.             this.Image = new Bitmap(this.Width, this.Height);
  9.  
  10.             this.solBrushAxis = new SolidBrush(Color.Black);
  11.  
  12.             this.colorPenBlackAxis = new Pen(this.solBrushAxis, (float)(2)); //brush
  13.             this.fontForLabels = new Font("Courie New", 6, FontStyle.Regular); //font for the label
  14.             this.pointOfLabel = new Point(1, 1); //point of the label
  15.  
  16.             Point yAxis_Start = new Point(5, 8);
  17.             Point yAxis_End = new Point(5, 185);
  18.             Point xAxis_Start = new Point(5, 185);
  19.             Point xAxis_End = new Point(310, 185);
  20.  
  21.             this.gfx.DrawLine(this.colorPenBlackAxis, yAxis_Start, yAxis_End); //Y axis
  22.             this.gfx.DrawLine(this.colorPenBlackAxis, xAxis_Start, xAxis_End); //X axis
  23.             this.gfx.DrawString("100%", this.fontForLabels, this.solBrushAxis, this.pointOfLabel); //string drawing
  24.  
  25.             this.Image = bmp;
  26.         }
  27.  
And it is dragged in Designer mode
Expand|Select|Wrap|Line Numbers
  1.             this.graphBox1.AxisColor = System.Drawing.Color.Black; //originally it was Color.Empty
  2.             this.graphBox1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
  3.             this.graphBox1.GraphColor = System.Drawing.Color.Green; //Color.Epmty originally
  4.             this.graphBox1.Location = new System.Drawing.Point(258, 88);
  5.             this.graphBox1.Max_On_Yaxis = 0;
  6.             this.graphBox1.Name = "graphBox1";
  7.             this.graphBox1.Size = new System.Drawing.Size(321, 203);
  8.             this.graphBox1.TabIndex = 0;
  9.             this.graphBox1.TabStop = false;
  10.             this.graphBox1.X_EndPoint = new System.Drawing.Point(310, 185); //all of these were 0 originally
  11.             this.graphBox1.X_StartPoint = new System.Drawing.Point(5, 185);
  12.             this.graphBox1.Y_EndPoint = new System.Drawing.Point(5, 185);
  13.             this.graphBox1.Y_StartPoint = new System.Drawing.Point(5, 8);
  14.  
Mar 1 '10 #43
tlhintoq
3,525 Expert 2GB
Your constructor is missing

InitializeComponent();

And it is dragged in Designer mode
Expand|Select|Wrap|Line Numbers
  1.             this.graphBox1.AxisColor = System.Drawing.Color.Black; //originally it was Color.Empty
  2.             this.graphBox1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
  3.             this.graphBox1.GraphColor = System.Drawing.Color.Green; //Color.Epmty originally
  4.             this.graphBox1.Location = new System.Drawing.Point(258, 88);
  5.             this.graphBox1.Max_On_Yaxis = 0;
  6.             this.graphBox1.Name = "graphBox1";
  7.             this.graphBox1.Size = new System.Drawing.Size(321, 203);
  8.             this.graphBox1.TabIndex = 0;
  9.             this.graphBox1.TabStop = false;
  10.             this.graphBox1.X_EndPoint = new System.Drawing.Point(310, 185); //all of these were 0 originally
  11.             this.graphBox1.X_StartPoint = new System.Drawing.Point(5, 185);
  12.             this.graphBox1.Y_EndPoint = new System.Drawing.Point(5, 185);
  13.             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.
Mar 1 '10 #44
EARNEST
128 100+
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)?
Mar 1 '10 #45
tlhintoq
3,525 Expert 2GB
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?
Mar 1 '10 #46
EARNEST
128 100+
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.
Mar 1 '10 #47
EARNEST
128 100+
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
Mar 1 '10 #48
EARNEST
128 100+
Expand|Select|Wrap|Line Numbers
  1.         private void InitializeComponent()
  2.         {
  3.             this.bmp = new Bitmap(this.Width, this.Height);
  4.  
shows 100x50, while
Expand|Select|Wrap|Line Numbers
  1.             this.graphBox1.Size = new System.Drawing.Size(174, 127);
  2.  
Mar 1 '10 #49
EARNEST
128 100+
Is there a way to fix it (apart from instantiating in another method) ?
Mar 1 '10 #50

Sign in to post your reply or Sign up for a free account.

Similar topics

5
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...
2
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...
4
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...
1
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: ...
5
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...
29
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...
94
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...
12
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...
0
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...
4
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...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
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
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
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...
0
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...
0
marktang
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,...
0
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...
0
jinu1996
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...
0
tracyyun
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...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.