Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does one have to use the paintComponent method to draw in Java?

I hope this question is not going to be regarded as too general. I understand that to draw on a JPanel you override the paintComponent method and place all your drawing code within that method. My question is why! Why does Java not seem to allow/provide for drawing with methods such as panel.drawLine(x1,y1,x2,y2) or panel.drawText(text,x,y)? It was all so much easier in delphi. There must be a reason I just can't figure it out.

like image 479
Tony Wolff Avatar asked Dec 25 '22 23:12

Tony Wolff


1 Answers

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.

like image 200
MadProgrammer Avatar answered Jan 17 '23 16:01

MadProgrammer