How does paintComponent work?
The (very) short answer to your question is that paintComponent
is called "when it needs to be." Sometimes it's easier to think of the Java Swing GUI system as a "black-box," where much of the internals are handled without too much visibility.
There are a number of factors that determine when a component needs to be re-painted, ranging from moving, re-sizing, changing focus, being hidden by other frames, and so on and so forth. Many of these events are detected auto-magically, and paintComponent
is called internally when it is determined that that operation is necessary.
I've worked with Swing for many years, and I don't think I've ever called paintComponent
directly, or even seen it called directly from something else. The closest I've come is using the repaint()
methods to programmatically trigger a repaint of certain components (which I assume calls the correct paintComponent
methods downstream.
In my experience, paintComponent
is rarely directly overridden. I admit that there are custom rendering tasks that require such granularity, but Java Swing does offer a (fairly) robust set of JComponents and Layouts that can be used to do much of the heavy lifting without having to directly override paintComponent
. I guess my point here is to make sure that you can't do something with native JComponents and Layouts before you go off trying to roll your own custom-rendered components.
How to make the paintComponent method work?
You need two additions in main method for this to work. You have to instantiate the MyDrawPanel() class and then add it to the frame.
MyDrawPanel p = new MyDrawPanel();
and
frame.add(p);
So the main method should be:
public static void main(String[] args) {
JFrame frame = new JFrame();
MyDrawPanel p = new MyDrawPanel();
frame.add(p);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 300);
frame.setVisible(true);
}
What is the JPanel/Graphics method paintComponent?
Why is paintComponenet used twice, for the name of the method and as we call a method from super (JPannel)
It's not "used" twice. It is overridden once, but you want to call the parent (JPanel) class's super method so that you're sure that it does its own house-keeping painting, including painting its children and clearing out any dirty bits from the screen.
What is Graphics g, isn't it just a reference variable for an object of Graphics since we don't set it equal to = new Graphics();
It's a Graphics parameter. You don't set it = new Graphics()
because the JVM does this for you. It calls the method behind the scenes when needed, and provides the parameter.
Why does the method name in my class have to be paintComponent to call upon the method paintComponent from JPannel or super
It has to override the super's method so that the JVM calls the right method when it wants to draw the GUI.
The method in my class paintComponent takes the parameter of a Graphics object but when does paintComponent even get called and when is the parameter of Graphics inserted.
Again, it is called by the JVM when either your program wants to repaint the GUI, such as when you call repaint()
or when the operating system wants to repaint a window such as if a window is minimized and restored.
You really really want to read the graphics tutorials:
- Lesson: Performing Custom Painting: introductory tutorial to Swing graphics
- Painting in AWT and Swing: advanced tutorial on Swing graphics
What does super.paintComponent(g) do?
- What does it do?
It prints the component as if you hadn't overridden the paintComponent
method. If you have a background color set for instance, this is typically painted by the class you're extending.
- When do we need to use it?
You use it if you don't paint on the entire component. The parts that you don't paint will "shine through" which means that you should let the super class paint those parts. As with the example of the background color for instance: If you just paint a circle in the middle of the component, super.paintComponent
will make sure the background color is painted around the circle.
If you do paint the entire area of your component, then you will paint on top of whatever super.paintComponent paints and thus there's no point in calling super.paintComponent.
- What advantage does it gives us by writing it in paintComponent()?
That's the only logical place to put it. paintComponent
is called when the component should be painted, and, as mentioned above, if you don't paint the entire component yourself, you need super.paintComponent
to paint on the parts that shine through.
The documentation of paintComponent
says it pretty well:
[...] if you do not invoker super's implementation you must honor the opaque property, that is if this component is opaque, you must completely fill in the background in a non-opaque color. If you do not honor the opaque property you will likely see visual artifacts.
Why does one have to use the paintComponent method to draw in Java?
That's because that's the way it works. It was designed this way. But I guess your question is about "why"
Remember, Swing first came out nearly 15 years ago. One of the criticisms was that the API was slow (the fact was, it was slow because people didn't truly understand how to use it, but that's another story), so the API had to be designed with performance in mind.
There are a number of factors involved...
Swing uses a passive paint process, meaning that the paint requests are made to the paint sub system and schedule (back on the EDT) for processing. The paint sub system makes decisions about what, when and how much should be painted. This is done at the desecration of the paint sub system.
This means that you never really know when a paint cycle may be executed, so we need some way to be able to respond to these requests.
Versatility is another factor. The API is abstract enough that it doesn't matter (a lot), where the component is being painted to. That is, you could be being painted to the screen, printer or even a image. This means you don't have to repeat a lot of paint code to make it work on different devices.
You also never know when a component will become displayable (that is, when it becomes attached to a native peer). This means that the graphics context may be null
, so having "helper" methods may actually cause more problems. When paintComponent
is called, you are (mostly) guaranteed to have a valid graphics context to paint to.
Extendability would be another factor. Not only is it very easy to override the paintComponent
to alter the way some component paints, it's also possible for the paint system to provide a extended Graphics context, as is the current case. When paintComponent
is called (by the paint sub system at least), it guarantees that the Graphics
context will be an instance of Graphics2D
, which is an extension to Graphics
, providing a number of important enhancements to the API.
This is all done without the need to change the base class which people are using, so if they don't want to use these features, they remain unaffected by them.
You may want to take a read through...
- Painting in AWT and Swing
- Passive vs. Active Rendering
For more details
And remember "Painting is fun" ;)
Additional Thoughts
One of the other considerations to take into account is the fact the the Graphics
API is central to painting, not just with consideration to the UI, but also printing and image manipulation. The API is disconnected from it's target, allowing a greater deal of flexibility, but also commonality.
This means that if you need to print to a printer or render to an image, you can use the same API you would for painting to the screen.
Related Topics
Good Hash Function for Strings
How to Generate a Random Biginteger Value in Java
Loading a Properties File from Java Package
How to Write Data with Fileoutputstream Without Losing Old Data
How to Load Rsa Private Key from File
Playing Mp3 Using Java Sound API
Should I Keep My Project Files Under Version Control
How to Use Xpath on Xml Docs Having Default Namespace
Different Dependencies for Different Build Profiles
How to Convert a Map to List in Java
Junit: How to Simulate System.In Testing
Difference Between Java.Lang.Runtimeexception and Java.Lang.Exception
Can a Java Class Add a Method to Itself at Runtime