简体   繁体   中英

java paint(g), repaint(), update(g) backend and local repaints

I have been discussing this topic a lot today with a bunch of fellow students that each work on different ideas to "misuse" the Java2D API for a simple 2D game.

I am using a class extending JComponent and override the paintComponent() method to get the Graphics2D object and from there on define my rendering logic. The modified JComponent is the contentPane of my overlaying JFrame .

Here comes my question: What different things does calling paint(Graphics) , repaint() and update(Graphics) in the JFrame 's backend do to my screen? I mention that when calling anything but repaint() from my "Frame Timer" (calling the method in question 50 times a second) some parts of the screen are flickering sometimes, some things I clearly tell it to render are not visible (or flickering rapidly) and everything just feels wrong. What is the difference here? I tried to dig into the source of the AWT backend up to the EventQueue where the PaintEvent is somehow managed but I stopped there to save my brain from extremely ugly code.

Also when discussing the whole repaint() thing we came to the "strategy" of only repainting places of the screen that correspond to definite changes in the model, saving us CPU/GPU power. Though it still needs logic to get these things done (as well as animations), the next question is how I can "access" the FrameBuffer of the painted screen so I can reference work that has already been done by my rendering.

And yes we already heard more often enough that Java might not be the programming language that supports all operations we are looking for in the best way...

Here comes my question: What different things does calling paint(Graphics), repaint() and update(Graphics) in the JFrame's backend do to my screen? I mention that when calling anything but repaint() from my "Frame Timer" (calling the method in question 50 times a second) some parts of the screen are flickering sometimes, some things I clearly tell it to render are not visible (or flickering rapidly) and everything just feels wrong. What is the difference here? I tried to dig into the source of the AWT backend up to the EventQueue where the PaintEvent is somehow managed but I stopped there to save my brain from extremely ugly code.

Scheduling painting in Swing is the responsibility of the RepaintManager . It is (amongst other things) responsible for determining what areas of the application need to be repainted and scheduling those updates to occur within the context of the Event Dispatching Thread.

When a repaint may occur is entirely up to the repaint manager. What areas are repainted is also, in part, up to the repaint manager and the repaint manager may choose to consolidate a number of repaint requests into a single repaint event, saving time and CPU.

In general, you should never call paint(Graphics) or update(Graphics) , apart from the fact that you can't actually create a graphics context, the repaint manager will do this for you. Even if you want to print the screen, you should use the component's print(Graphics) method, apart from the fact that it's not double buffered, there are issues related to trying to copy the buffer back to the native peer ;)

Flickering generally occurs because you are painting from a non-double buffered context, such as overriding paint instead of paintComponent . Generally speaking, it would a very rare case where you actually need to override the paint method of a top level container like JFrame

Also when discussing the whole repaint() thing we came to the "strategy" of only repainting places of the screen that correspond to definite changes in the model, saving us CPU/GPU power. Though it still needs logic to get these things done (as well as animations), the next question is how I can "access" the FrameBuffer of the painted screen so I can reference work that has already been done by my rendering.

Generally, unless you have a real need to do so, don't worry about it. If you're careful with your repaint code (you can actually schedule an area to be repainted, rather then repainting the whole component), you shouldn't really need to care. Make sure you are using a ancestor of JComponent and using the paintComponent method and you gain automatic double buffering...

The other problem is, you really don't know when a component might request a repaint of it self, such as in response to a mouse movement or change in the components properties...

Accessing the "frame buffer" probably really isn't a good idea, what would be better is to generate your own buffer (using something like a BufferedImage ), render to it and then render that to the screen (off screen buffering). This way you would be generating your own "FrameBuffer"

Now, if you're really desperate, you could take a look BufferStrategy

But I would suggest you take a look at Painting in AWT and Swing before you delve to much further, this will give you a deeper understanding of how painting works.

Also, don't EVER think you are in control, you're not. If you try and "take" control, be prepared for things to blow up in your face quickly. Understand the process and work with it.

Take a look at these (simple) examples...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM