Active rendering and the EDT (Swing animation) - java

How should I run animation in a Swing applet?
I have an animation thread performing active rendering and it initially animates fine. Sometimes (anywhere from 1 minute to 2 hours later) it begins to fail to update the screen and only the sounds occur. I believe this is due to the fact that the paint is not performed from the EDT causing some kind of concurrency problem.
So, should the active rendering (ie getGraphics() and painting) be called only from the EDT? A problem with this is the Swing timer lacks precision.
Or has anyone had success with active rendering without using the EDT, and completely disabling any EDT updates to the page (maybe using Canvas / or ignore repaint on a JPanel)?

You can paint graphics into your own off-screen image in another thread and copy to the screen in the EDT. But for single threaded stuff, I would hope your frame rate is high enough to be able to do it in the EDT.

A few things to look at would be to make sure you are only repainting what needs to be repainted and not the whole graphics context each time unless necessary. Also there is a timing framework that you can use to handle some animations. I don't think it is actively being developed but last time I looked at it it had some nice api's to use for animation.
Without knowing your specific use case this is all I could come up w/ off the top of my head.

Related

Drawing frequently updated Graphics inside a complex Swing UI without blocking Event Dispatch Thread

I'm developing a plugin for an old application that uses the Swing UI toolkit. As far as I know, Swing's philosophy is that everything executes on the Event Dispatch Thread. I need to integrate a JPanel where it repaint()s itself every 16ms.
I think this will cause the EDT to be flooded with redrawing that JPanel and making other events wait longer, (mentioned in the Javadocs) which could slow down the app. I'm already seeing slowdowns in a test instance of the application.
The way I see it now there are 2 solutions:
Render everything to an image, then render that to the screen, this way, long computations can be rendered by a background thread and the EDT takes care of drawing a simple image, reducing latency.
Make repaint calls only when the user is actually doing something.
What is a performant way to draw dynamic, frequently-updated content inside a Swing UI without blocking the EDT and the rest of the UI?
The animation, processing changes painting complex modelling objects on a Graphics/Graphics2D can indeed be separated. Whether SwingWorker, SwingTimer, event driven.
You can use a BuffferedImage with getGraphics and at the end of Graphics2D drawing do a disposeGraphics. Take a compatible image type as the Graphics of the screen.
Then the actual painting will just do a drawImage in the paintComponent update event handling.
Log processing times, and repaints - for optimization. This profiling is crucial to knowing performance bottlenecks.
Often costly things can be improved. Like using affine transformations, preloaded images of course, and so on. Like doing light-weight drawing instead of tiny JComponent hierarchies. Like pruning invisible parts.

Serious Performance issue using JLayer drawing with AquaLookAndFeel

I'm having a serious performance issue using a JLayer to do special drawing, but only under the AquaLookAndFeel on Macintosh. Using any other look and feel, the performance is fine.
Here's the scoop:
I have a test case that blurs the main window when a child dialog pops up above it. On most L&Fs it works fine. On Aqua, it takes five seconds to draw, and the screen is frozen the whole time. I can press OK to dismiss the dialog, but it doesn't respond until it's done drawing. And the reason it takes so long to draw is because Aqua is firing multiple paint events. For every component that might change its visual state, it fires a paint event. So it redraws the entire window, using the blur effect, once for each of the twelve JButtons or Checkboxes in the window. The blur effect takes about one third of a second to draw, but it takes about 5 seconds with all the repaints.
Under any other look and feel, only two paint events are fired, so the performance is acceptable.
To see this in action, run the test case at https://github.com/SwingGuy1024/Bugs/blob/main/AquaPaintBug.java
It lets you try it under different looks-and-feels. It runs fine on all but Aqua.
Has anyone else seen this? Does anyone know of a workaround? Is this a bug in Aqua, or am I missing something? If I can't use JLayer to enhance the drawing of a component, the JLayer is useless for drawing.
Note: I think this is partly caused by a PropertyChangeListener that gets set by the AquaRootPaneUI class, on a property called AquaFocusHandler.FRAME_ACTIVE_PROPERTY, which is defined as "Frame.active". This seems to get activated when the window's active state changes, which is what happens when a dialog opens up. This explains why it repaints all the JCheckBoxes, but doesn't explain why they each get a separate paint event.

Is Java Swing blocking UI while painting/rendering?

I'm writing an editor and I have some performance issues. The thing is when there is a lot of text (10K Lines) in the editor Swing blocks (gets really slow) the UI because there is a lot of words to highlight (re-paint/re-render).
I'm also using EDT (Event Dispatch Thread).
Does swing block UI when painting/rendering? Is there any way to optimize rendering while I type some words to the editor (like async painting etc.)?
As you already mentioned, take care to always call Swing painting operations on the event dispatching thread by using SwingUtilities.invokeLater(Runnable) or SwingUtilities.invokeAndWait(Runnable). Otherwise you'll get into trouble and have responsiveness issues that can ultimately lead to the so called 'Grey-Rect-Problem' where your frame is rendered as a grey rect and the UI does not respond anymore (keyboard, mouse events and so on).
Difference between invokeLater and invokeAndWait is that invokeLater causes the java.lang.Runnable you pass to it to be executed asynchronously on the AWT event dispatching thread. I don't know how you ensure that your painting operations are done on the EDT - so if your're not already using invokeLater try this out first.
Other than that, as a general rule for optimisation of UI performance: Always try to minimize the area that has to be repainted! E.g. by using java.awt.Component.repaint(long tm, int x, int y, int width, int height), which repaints a specific area of a UI component in between a specified time.
Maybe these links also helps:
JTextArea setText(veryLongString) is taking too much time
https://pavelfatin.com/low-latency-painting-in-awt-and-swing/

Best Timer Designs for Java2D video games

I am building a Java2D video game with multiple sprites updating on the screen at once, and was looking for feedback with regard to best way to handle updates via use of Timers.
I was looking for feedback on best way to handle Timer design that would update locations of each Sprite. Currently, the way I have been doing it, is I have one Timer. When it expires, I update the position of each Sprite. I only ever Update Sprite location by 1 pixel, to keep motion smooth. If something was to update slower that then rest of the Sprite, I update it's position say on every 3 or 5th call of a getImage() call (used to get the current icon image of the sprite).
Now with this approach, all updates are dependent on the main timer, and the Sprites sort of update in relation to each other. So if I wanted to speed up the game, I just update the refresh rate of the main timer.
However, I don't know if this is the best approach. Would it be better to put each object on it's own timer, but would that cause other issues? Maybe cause problems for the main paint() method?
Was just looking for feedback on a good design technique for this.
It is possible to keep using one timer while having perfectly smooth animations despite different animation and movement speeds between different sprites. The way to do is by changing your animation and movement of sprites from a tick based approach (move x many pixels per update) to a time based approach (move x many pixels per how much time has elapsed since the last update).
This would mean your Sprite class (or whatever you have), has floating point x and y positions, as well as floating point x and y velocities. To change the speed of a certain sprite, you would change the velocity (which would be pixels/drawingUnitsEtc per millisecond/nanosecond), and won't be limited by how fast you can make the timer run.
However, I don't know if this is the best approach. Would it be better to put each object on it's own timer, but would that cause other issues?
Well if you did use a timer per Sprite that used a different speed, you would run into overhead problems if the timers ran on their own thread, and if the timers were executed on the same thread then you are technically updating your Sprites based on how much time has elapsed but just moving the velocity constant to an integer.
You would also run into a problem of how you can ensure the Timer consistently returns. With separate timers, imagine that there may be two sprites that are walking next to each other in game which want to update at 10ms, but one of them is running at 11ms due to a laggy timer, eventually one will run into the back of the other and turn around and mess up your level design or some other game mechanic. Another one is that they could be two Sprites of the same kind but now one is now an animation frame ahead of the other while that didn't hold true for the first few seconds that you saw them. With a single timer that updates all sprites that operate together you'll get those consistent results.
Assuming you're using java.util.timer's schedule method.
You could use the scheduleAtFixedRate method for cleaner looking code.
Only use one instance of Timer and attach all sprites to it, this keeps all sprites running on the same thread because then you eliminate all forms of concurrent modification, using a new thread for each sprite is way overkill as the threads will be running as fast as possible and maxing out the computer.
You could also simply make something along the lines of a SpriteManager class which extends Thread so that you don't even need to use timer, all sprites will be running as fast as possible but on one thread, it wont put too much load on the cpu but it worth it. Professionally, movement falls under physics so a game would have some physics thread that handles all updates to everything.
You could get even more detailed in the physics thread by realising that throughout the course of gameplay the amount of objects on the thread will change therefore will update less frequently making everything slower (even if it is microseconds). To keep everything running smoothly you can delta scale. Delta scaling simply takes the time it took last frame as a hint to how fast the thread is running and scales the speed of objects up or down appropriately - this is how (most) games don't run slower when the frame rate drops, instead, they look like they jumped to where it would be at that point in time.

Java Swing animation ghost issue

Just a forewarning: I'm new to java - I normally use UnrealScript and C# but I'm branching out, so there is likely one or two things I've done incorrectly or against the normal java convection (that would be more in align with convictions of those other two languages)
Feel free to point them out, and I'll mold myself to them accordingly
I'm making a JRPGish style game in java using BlueJ. I'm not aiming massively high, and am more doing it as a proof-of-concept rather than a full blown game.
So far its going ok. I'm got a sprite animation working using a sprite sheet and the player can walk around with the sprite changing to the correct animation depending on the direction.
However I'm having an issue when the player stops moving - there sometimes is a afterimage of the previous frame - In fairness, this may be happening all the time except you cant see it if the player stops moving on the first and last frame of the walking animations, as those take up the same pixel space and thus are hidden (if that makes sense)
Here is an image of the issue in action:
This is after the player has moved, and then stopped, leaving the last frame of the "moveRight" sprite behind.
I have created a small version of my project that has just the character animation playing when you press a key, and stopping when you release, in which the issue appears
The Skeleton class
The Character class
The GameManager class
The KeyManager class
To start the game run the Main method in GameManager
You'll need to save this image with the filename of "James.png" and place it in the same folder of the java project for it to work
Thanks in advance for any help given.
paintComponent() passes Graphics to drawCharactor(). drawCharactor() should not disposes that Graphics object unless you made a copy, this Graphics is shared.
Also, do not call repaint() from drawCharactor(). repaint() schedules another paint cycle. You already do call repaint() from a timer.
Do not use java.util.Timer use javax.swing.Timer for Swing painting. See How to Use Swing Timers
For more information and examples Performing Custom Painting and Painting in AWT and Swing.
Consider posting a minimal example.

Categories

Resources