im making a java swing game. I heard that swing components don't use active rendering(you can only override paint methods), and for that reason, i have been using BufferStrategy with Canvas. Now i have discover the getGraphics() method from JComponent and JPanel. If we can do active render in swing components, why game tutorials still override paint() and paintComponent()?
Don't EVER use getGraphics, it can return null and is nothing more the a snap-shot of the last paint cycle.
Anything you paint to it will be removed on the next paint cycle. In Swing you DON'T control the paint process and a paint cycle could be initiated for any number of reasons, many of which you don't have control over or would notified of (other then when paint was called)
The basic answer is, if you want control over the paint process, you MUST use a BufferStrategy or implement you own off screen drawing routines. There is NO means by which you can achieve a true active painting process within the Swing API, you can fake it to a certain extent, but Swing will still be able to perform it's own painting cycles when it sees fit.
Have a look at Painting in AWT and Swing and Performing Custom Painting for more details about how painting works in Swing
Related
I'm new to graphics in java and am having difficulty grasping the whole concept of drawing all your graphics from one method (paintComponent ()). I was just curious to see if we can draw graphics outside the paintComponent. Is that even possible? is it possible to write a line in the main method like:
fillRect(100,100, 500,400);
and have it draw a rectangle?
If it is possible, is it conventional according to Java?
Basically, I'm asking if you can draw graphics outside the paintComponent class and is it conventional.
You can draw to a BufferedImage, but if you want it drawn on the screen then generally, you'll need to use paintComponent. You can pass the instance of Graphics which is passed into paintComponent to other classes which can do more complex operations, but you should never maintain a reference that instance or try painting outside of a paint cycle context.
See Painting in AWT and Swing and Performing Custom Painting for more details
If you need more control over the paint process you could also use a BufferStrategy
See BufferStrategy and BufferCapabilities for more details
Things you should know:
Swing uses a "passive rendering" approach, this means that painting occurs when the paint system decides it needs to be done. This is why you MUST perform your painting within the context of a paint cycle (ie - in the paintComponent method)
BufferStrategy uses a "active rendering" approach, which gives you complete control of the painting process, but it's not capable of painting Swing components
I am wondering whether I am able to use the paint method of Java's graphics class on something other than a JFrame--that is, no JFrames allowed. Is it possible?
Thanks in advance!
Graphics represents a graphic context, i.e. something you can draw on. In addition to GUI components like JFrame, JPanel etc. providing getGraphics() to access the visible gfx context, another common class that allows access to a gfx context is BufferedImage (or Image classes in general).
While painting on a visible GUI element immediately shows the results of the painting, using a BufferedImage allows you to perform the painting off screen into a buffer, and then painting the whole image at once (on a JFrame as you still need something visible) when you're ready to display the image. This is often used in animation and games when you need to avoid flickering for example.
I am reading this article on Painting in AWT and Swing which have following paragraph in section "How lightweights get painted"
It's worth noting that the default implementation of Container.update() does not use recursion to invoke update() or paint() on lightweight descendents. This means that any heavyweight Container subclass that uses update() to do incremental painting must ensure that lightweight descendents are recursively repainted if necessary. Fortunately, few heavyweight container components need incremental painting, so this issue doesn't affect most programs.
Please tell me, in which case do I need to have recursive calls to update() or paint() and why?
You don't need recursive calls to update() or paint().
If you want to paint a component all you do is:
component.repaint();
This will add a paint request to the RepaintManager to paint the component and Swing will make sure that the components child components get painted when the paintChildren(...) method is invoked. See A Closer Look at the Paint Mechanism for more information.
My question is whether the use of setOpaque(false), which I've come to use with JPanel to layout UI in Swing, impacts painting performance more than keeping everything opaque (where isOpaque() returns true).
I'm not very familiar with how Swing renders UI but I would guess that if a JComponent is not opaque it would be harder to render what's behind the component then to simply paint an opaque background on the component.
Yes it does add extra work when painting but I doubt you would have to worry about it.
Basically, whenever you repaint a component that is transparent you need to go up the chain to find a parent that is not opaque and then paint that component first, before painting the child component.
So the bottom line is don't worry about it. If you have a reason to use transparency then use it. If you don't have a reason then you shouldn't be using it.
You may want to check out Background With Transparency. It goes into a little more detail on what the opaque property means and how it affects painting and the problem you will have if you do use a transparent background.
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)