The paint method:
Invoked by Swing to draw components. Applications should not invoke paint directly,
but should instead use the repaint method to schedule the component for redrawing.
This method actually delegates the work of painting to three protected methods:
paintComponent, paintBorder, and paintChildren. They're called in the order listed
to ensure that children appear on top of component itself. Generally speaking,
the component and its children should not paint in the insets area allocated to the
border. Subclasses can just override this method, as always. A subclass that just
wants to specialize the UI (look and feel) delegate's paint method should just
override paintComponent.
Parameters:
g the Graphics context in which to paint
public void paint(Graphics g)
I've read many times not to override paint(), but to override paintComponent() instead. As seen above, the documentation also suggests to override paintComponent() if you want to specialize the UI.
So, I wanted to trace through the code to see why this is so.
protected void paintComponent(Graphics g)
{
if (ui != null)
{
Graphics scratchGraphics = (g == null) ? null : g.create();
try
{
ui.update(scratchGraphics, this);
}
finally
{
scratchGraphics.dispose();
}
}
}
There are many methods to trace through, but for conciseness, here's update():
public void update(Graphics g, JComponent c)
{
if (c.isOpaque())
{
g.setColor(c.getBackground());
g.fillRect(0, 0, c.getWidth(),c.getHeight());
}
paint(g, c);
}
An overloaded version of paint() is called, and paint(), itself, calls paintComponent(). So, I guess I'm just trying to figure out what's going on here exactly. I'm very new to Swing; there are a lot of classes and it's pretty difficult to trace through all of them, especially with my limited knowledge of using GUIs, in general.
Are these methods constantly calling each other, thereby giving the illusion of an image on the screen? If so, why does it matter so much if you override paint() instead of paintComponent? I imagine that my logic is in some way flawed or lacking, considering that for applications, the documentation advises against invoking paint() directly, and instead suggests to invoke repaint(). So, basically, I'm just trying to get some insight into the overall relationship between paint(), paintComponent(), repaint(), etc.
Firstly take a look at...
Performing Custom Painting and
Painting in AWT and Swing
The second should be compulsory reading for all Swing developers.
paint is (within the context of this question) the top level method called (update is actually called first, which just forwards to paint) when the RepaintManager wants a component to be painted.
paint is responsible for (amongst other things) calling paintComponent, paintBorder and paintChildren. If you're not careful you could compromise your components ability to paint. So if you HAVE to override paint, make sure you are calling super.paint.
It's important to note, the if a child component is updated, the parent component may not be repainted, so it don't try and use paint to provide overlays for your component.
paintComponent is responsible for painting the "background" of the component. This basically delegates to the look and feel.
In the case of something like JPanel, it will fill the background with the background color (if set to opaque). In the case of something like JTable, it will paint the rows, columns and cell values.
It is very important to ALWAYS call super.paintComponent, especially when dealing with transparent components.
repaint will make a request to the RepaintManager which may consolidate the paint requests so as to reduce the actual number of paint events that are raised. This helps improve performance.
The important thing to note here is that you don't control the paint process, so don't try, work with it instead.
Your paint method is also expected to run quickly, so avoid time consuming operations, like loading resources, or compound loops where possible. If you can, create backing buffers and paint those instead
ps- Paint is fun ;)
Related
This is The Code :
public void paint(Graphics g) {
g.fillOval(x, y, 25, 25);
repaint();
}
This will create an output like This where if i move the pointer it doesn't clear the previous Graphics and creates a Path .
Output of Above Code
And by adding the super statement like this it Doesn't show the Path but only the Current location of the Oval Graphic.
public void paint(Graphics g) {
super.paint(g);
g.fillOval(x, y, 25, 25);
repaint();
}
The output is This
I just want to the Mechanism and The Reason Behind This.
Sorry, but there is so much wrong with your code, that we have to fix it:
First off, don't override a JComponent's (or JFrame's) paint method but rather override the JComponent's or JPanel's paintComponent. This way you avoid mistakingly messing up painting of borders or child components, both of which paint is responsible for. Also since paintComponent has automatic double buffering, your animation will be much smoother.
Next, you almost always do want to call the super's painting method, which for paintComponent is super.paintComponent(g) as this will continue to propagate the painting chain, whereas by not calling this you break this chain. Calling the super's method will call the component's housekeeping painting including the overpainting of "dirty" pixels which is why the trails are removed. This is likely the answer that you're looking for.
Most important never call repaint() from within any painting method. Doing this results in a poor-man's animation that is completely uncontrollable, and puts too much responsibility on the painting method which should focus on its sole job -- to paint the component. Use a game loop such as a Swing Timer instead.
Most important -- read the tutorials as most of this is already explained there:
Lesson: Performing Custom Painting: introductory tutorial to Swing graphics
Painting in AWT and Swing: advanced tutorial on Swing graphics
Straight from the docs
public void paint(Graphics g)
Paints the container. This forwards the paint to any lightweight
components that are children of this container. If this method is
reimplemented, super.paint(g) should be called so that lightweight
components are properly rendered. If a child component is entirely
clipped by the current clipping setting in g, paint() will not be
forwarded to that child.
As he said that super.paint() cleans the dirty pixels. This says it all .!! :)
What is the actual difference between paint(), paintComponent() and paintComponents() in Java Swing?
I tried to understand what explained in Oracle docs but I am not clear.
AWT, override paint().
Swing top-level container (e.g.s are JFrame, JWindow, JDialog, JApplet ..), override paint(). But there are a number of good reasons not to paint in a TLC. A subject for a separate question, perhaps.
The rest of Swing (any component that derives from JComponent), override paintComponent().
Neither override nor explicitly call paintComponents(), leave it to the API to call it when needed.
Be sure to also use #Override notation whenever overriding a method.
Doing so would hint at the problem of trying to override paintComponent(..) in a JFrame (it has no such method), which is quite common to see.
You may be interested in reading Painting in AWT and Swing
A quote:
The rules that apply to AWT's lightweight components also apply to Swing components -- for instance, paint() gets called when it's time to render -- except that Swing further factors the paint() call into three separate methods, which are invoked in the following order:
protected void paintComponent(Graphics g)
protected void paintBorder(Graphics g)
protected void paintChildren(Graphics g)
Swing programs should override paintComponent() instead of overriding paint(). Although the API allows it, there is generally no reason to override paintBorder() or paintComponents() (and if you do, make sure you know what you're doing!). This factoring makes it easier for programs to override only the portion of the painting which they need to extend. For example, this solves the AWT problem mentioned previously where a failure to invoke super.paint() prevented any lightweight children from appearing.
I have tried tutorials on this but I still don't quite understand it. Basically my question is which method is better and why? Should I use paint or paintComponent?
Please try to keep the answer simple, thanks.
Quoting from documentation of paint() method
This method actually delegates the work of painting to three protected methods: paintComponent, paintBorder, and paintChildren.
...
A subclass that just wants to specialize the UI (look and feel) delegate's paint method should just override paintComponent.
It looks like the paint() method actually draws the component, including the border and children. If you only want to customize the component's appearance excluding the border and children, you use paintComponent().
http://docs.oracle.com/javase/7/docs/api/javax/swing/JComponent.html#paint(java.awt.Graphics)
Generally speaking, when painting in Swing, it is recommended to override paintComponent.
There are a number of reasons why, one is paintComponent is painted at the bottom layer, meaning you won't accidentally wiping out any components that were rendered during the paint process - this happens a lot to people who post here.
There are a, very, few times you might need to override paint, but I would always encourage you to try making it work with paintComponent first.
Check out
Performing custom painting
Painting in AWT and Swing (+1 to trashgod)
I'm trying to implement a simple window scale in java's swing library. The goal is simply to double the window height and width, and paint the window and each of its components in scale.
Here's an example of the code I'm using:
public class MyWindow extends JFrame {
...
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.scale(2,2);
super.paint(g);
}
}
The position and size for each my components in this window is set manually using setBounds with a null layout for the window.
When I actually run the program, what happens is that the first paint for the window seems successful-- everything is sized appropriately. Each subsequent repaint by the components, however, is neither twice the size, nor in the proper location. Here's what I mean:
As you can see, portions of the screen which have components that call repaint manually (the animating bits), don't seem to be using the Graphics2D scale of the JFrame. I looked in the source code, and tried overloading a few other methods (update and repaint, mostly), but all of them seemed to produce the same result. I further looked at the paint and repaint methods of the component and container classes, but they all seem to call a specified repaint of their parent. Shouldn't my Window be the "biggest" parent? If so, why haven't these repaint calls reached my Window?
My big question to you is, therefore: what repaint methods of the parent component do the child components call? Why aren't the calls properly routed to my JFrame's paint call? Is there any other (better) way that I can scale my window? Any and all help is appreciated!
As discussed in Painting in AWT and Swing: The Paint Methods, "Swing programs should override paintComponent() instead of overriding paint()." A common approach is to create a view by overriding paintComponent() in a JComponent (or subclass), as shown here. Let your view listen for changes to the game's model, as discussed here.
SwingUtilities.updateComponentTreeUI() should be used to change the Look & Feel, not update the view.
Use
javax.swing.SwingUtilities.updateComponentTreeUI(parentComponent);
when you need to make sure all of the parentComponents child component's look and feel are updated properly.
What is the actual difference between paint(), paintComponent() and paintComponents() in Java Swing?
I tried to understand what explained in Oracle docs but I am not clear.
AWT, override paint().
Swing top-level container (e.g.s are JFrame, JWindow, JDialog, JApplet ..), override paint(). But there are a number of good reasons not to paint in a TLC. A subject for a separate question, perhaps.
The rest of Swing (any component that derives from JComponent), override paintComponent().
Neither override nor explicitly call paintComponents(), leave it to the API to call it when needed.
Be sure to also use #Override notation whenever overriding a method.
Doing so would hint at the problem of trying to override paintComponent(..) in a JFrame (it has no such method), which is quite common to see.
You may be interested in reading Painting in AWT and Swing
A quote:
The rules that apply to AWT's lightweight components also apply to Swing components -- for instance, paint() gets called when it's time to render -- except that Swing further factors the paint() call into three separate methods, which are invoked in the following order:
protected void paintComponent(Graphics g)
protected void paintBorder(Graphics g)
protected void paintChildren(Graphics g)
Swing programs should override paintComponent() instead of overriding paint(). Although the API allows it, there is generally no reason to override paintBorder() or paintComponents() (and if you do, make sure you know what you're doing!). This factoring makes it easier for programs to override only the portion of the painting which they need to extend. For example, this solves the AWT problem mentioned previously where a failure to invoke super.paint() prevented any lightweight children from appearing.