• Post Reply Bookmark Topic Watch Topic
  • New Topic

the best way to create a scatterd plot graph

 
Joseph Cho
Ranch Hand
Posts: 44
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

I've been reading HeadFirst's Java book, and I am on the swing chapter where it gives examples of overriding the paintcomponent method. There is an example of an "animation" of a moving a circle inside of a JPanel. The panel is created by creating a subclass of JPanel (which is also an inner class) with a background color set by setting a rectangle to the background of the JPanel and settings its color. It then states to put the main Thread to sleep for .5 seconds to slow it down enough to actually see the circle moving as you change its X and Y coordinates. The problem now is to overcome "smearing." It demonstrates the best way to do this is to redraw a rectangle each time and then redraw the circle in its new place. My first reaction is, wouldn't this keep painting a bunch of rectangles on top of each other causing more memory than normal to be used?

Also, I came across this article on here:

http://www.coderanch.com/t/345317/GUI/java/clear-JPanel-repainting

Which shows that super.paintcomponent(g) will clear the panel before each paint. The headfirst book demonstrated the moving circle without making use of the super.paintcomponent(g), any ideas why?

Finally, reading all of this has got me wondering that lets say I wanted to create a scattered plot graph where the user can see it grow as it is being plotted instead of assigning all the dots and calling repaint(). If I call super.paintcomponent, wouldn't this erase all the prior dots? What would be the most efficient way to create this graph?

Thanks!
 
Darryl Burke
Bartender
Posts: 5155
11
Java Netbeans IDE Opera
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I haven't read the book you refer to, but calling sleep(...) on the EDT is just plain wrong.

For your question, take a look at the tutorials on How to Use Swing Timers and Collections. You can add points to a List each time a Timer is triggered and iterate over the List to draw the points in a paintComponent(...) override.

Now may be a good time for you to also get familiar with Concurrency in Swing.
 
Rob Camick
Ranch Hand
Posts: 2700
10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If I call super.paintcomponent, wouldn't this erase all the prior dots?


Correct, so your paintComponent() method needs to repaint everything every time it is called.

See Custom Painting Approaches for the two common ways to do this.
 
Piet Souris
Rancher
Posts: 1638
36
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
A JPanel's paintComponent does nothing more than clear the panel to its background.

If you draw then a rectangle the size of the panel, you are doing in fact double work.
So, if you do dwaw such a rectangle, there is no need to call super,paintComponent first.

Also, by default a JPanel uses 'double buffering'. When you draw to a JPanel, Swing
is drawing to (probably) some BufferedImage and then draws that BufferedImage
to the screen memory.

Now, if you want to see your scattergraph grow, then a possible strategy could be:

start a timer
in the actionPerformed method, call the panel's repaint() method
in the paintComponent() of the panel, draw one or more points, but DON'T issue super.paintComponent!
et cetera.

Of course, at some time you'll want to clear the panel, by pushing a button or some key. THEN you can call
super.paintComponent and start afresh.

By setting a suitable time delay in the timer, you can easily set the speed of plotting, without freezing your
GUI (which is what Darryl warns for).
.
 
Joseph Cho
Ranch Hand
Posts: 44
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks everyone for the responses, this was exactly the clarification I was looking for. Thanks for your time.
 
Darryl Burke
Bartender
Posts: 5155
11
Java Netbeans IDE Opera
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Piet Souris wrote:A JPanel's paintComponent does nothing more than clear the panel to its background.

If you draw then a rectangle the size of the panel, you are doing in fact double work.
So, if you do dwaw such a rectangle, there is no need to call super,paintComponent first.

Wrong. If you fill a Rectangle that covers the entire panel or otherwise paint all pixels of the panel, then you don't need to invoke the super implementation. Drawing a Rectangle only paints the pixels that fall on the Rectangle's outline.

Piet Souris wrote:Also, by default a JPanel uses 'double buffering'. When you draw to a JPanel, Swing
is drawing to (probably) some BufferedImage and then draws that BufferedImage
to the screen memory.

Since this is not specified in the API, speculation gets us nowhere. Moreover, it is sufficient to know that Swing implements double buffering by default; the actual mechanism is of no concern.

Piet Souris wrote:Now, if you want to see your scattergraph grow, then a possible strategy could be:

start a timer
in the actionPerformed method, call the panel's repaint() method
in the paintComponent() of the panel, draw one or more points, but DON'T issue super.paintComponent!
et cetera.

Oh yeah? and what's the result if the GUI is minimized and restored, or partly/fully covered by another application and then revealed?

DO issue super.paintComponent(). Iterate over a List of Points and draw them.

Piet Souris wrote:Of course, at some time you'll want to clear the panel, by pushing a button or some key. THEN you can call
super.paintComponent and start afresh.

And where do you obtain the Graphics reference to pass to the super implementation?

THEN you can clear the List of points or otherwise set a flag to indicate to the paintComponent(...) method that they shouldn't be drawn.
 
Piet Souris
Rancher
Posts: 1638
36
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
as always, friendly patient Darryl steps in wit friendly patient comment...

Maybe we should wait for Joseph's comments if it is not working in the way
he wants to. But indeed, patience is a great gift.
 
Piet Souris
Rancher
Posts: 1638
36
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Well,

to close my contribution to this topic some remarks to Darryl's comments. I think these could clarify some points.

Wrong. If you fill a Rectangle (...)

(How do you get the name of the quoted person in a quote?)

Yes, I was a bit hasty here. Should of course be fill.

Oh yeah? and what's the result if the GUI is minimized and restored, or partly/fully covered by another application and then revealed?


Covering and uncovering and dragging still work as I described, by this very double buffering. Try it and see for yourself.

It is when you resize (and when I drag the window to my second monitor, then halfway the monitor change...) when you see
that the system is doing a complete redraw, and it uses some (default?) gray background color for this.

And where do you obtain the Graphics reference to pass to the super implementation?

Simple. In the paintComponent(Graphics g) for the panel. That's the g.

My intention was to get Joseph his effect in an as simple way as possible. Indeed, it is not the most elegant way,
my description was a bit sloppy, and it has indeed it's drawbacks. That's why I wrote "(...) a possible strategy (...)"

And finally, I would not advise the use of a List or Array of points when doing a complete redraw, that is: not when you
call paintComponent() a lot. This will slow down the redrawing at some stage when more and more point are added.

Drawing the points to a buffered image would be much better, for the following reasons:

1) drawing this BI in the paintComponent() routine takes constant time
2) you get scaling to the panels size nearly for free
3) when you're finished with drawing points, you can easily save your scattergraph to disc.

Maybe there are even better or faster ways, I don't know.

Well, yesterday evening I have done some paintComponent() experiments, and noticed some things that I don't understand.
I'll put these in a new topic.
 
Darryl Burke
Bartender
Posts: 5155
11
Java Netbeans IDE Opera
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Piet Souris wrote:I would not advise the use of a List or Array of points when doing a complete redraw, that is: not when you
call paintComponent() a lot. This will slow down the redrawing at some stage when more and more point are added.

I invite you to run and play with the code I posted in this old thread on the Sun/Oracle forums, which uses a List of not just Points but graphical features which require much more complex painting, including construction of a few RadialGradientPaint instances* for each repainting.

Tell us if you notice any performance hit.

Oh, and you never call paintComponent(...) in your code. You call one of the two overloads of repaint().

* edit: construction of GradientPaints is known to be fairly computationally intensive
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!