AWT custom rendering - capture smooth resizes and eliminate resize flicker?

Here is code that renders with an outside Thread doing all the work. It does this by being able to render anything that implements the Renderable interface. I have tested this with both Swing and AWT ( JFrame and Frame ) and it works with no flickering.

Note, it does flicker if you implement onto a JRootPane and set that pane as the JFrame s root pane. This has to do with how the component is buffered, and could be fixed if that is how you want to use this.

Here is code that renders with an outside Thread doing all the work. It does this by being able to render anything that implements the Renderable interface. I have tested this with both Swing and AWT (JFrame and Frame) and it works with no flickering.

Note, it does flicker if you implement onto a JRootPane and set that pane as the JFrame's root pane. This has to do with how the component is buffered, and could be fixed if that is how you want to use this. If this is still not what you were looking for, just say and I'll give it another go.

This is actually fun, as it has been awhile since I've done any Java GUI work. Anyways, here you go: import java.awt. Color; import java.awt.

Dimension; import java.awt. Frame; import java.awt. Graphics; import java.awt.

Toolkit; import javax.swing. JFrame; public class SmoothResize extends Frame implements Renderable { public static void main(String args) { Toolkit. GetDefaultToolkit().

SetDynamicLayout(true); System. SetProperty("sun.awt. Noerasebackground", "true"); SmoothResize srtest = new SmoothResize(); RenderThread renderThread = new RenderThread(srtest); renderThread.start(); srtest.

SetSize(100, 100); srtest. SetVisible(true); } public SmoothResize() { } public void addNotify() { super.addNotify(); createBufferStrategy(2); } @Override public Dimension getSize() { return new Dimension(getWidth(), getHeight()); } @Override public Graphics acquireGraphics() { return this.getGraphics(); } } class RenderThread extends Thread { Renderable target; Dimension last_size = new Dimension(Integer. MAX_VALUE, Integer.

MAX_VALUE); public RenderThread(Renderable d) { if (d == null) { throw new NullPointerException("Drawable target cannot be null. "); } target = d; } @Override public void run() { while (true) { render(false); } } private synchronized void render(boolean force) { Dimension size; do { size = target.getSize(); if (size == null) { return; } Graphics draw = target.acquireGraphics(); if (draw == null) { return; } draw.setPaintMode(); int w = (int) (((double) (size. Width)) / 2 + 0.5); int h = (int) (((double) (size.

Height)) / 2 + 0.5); draw. SetColor(Color. YELLOW); draw.

FillRect(0, h, w, h); draw. FillRect(w, 0, w, h); draw. SetColor(Color.

BLACK); draw. FillRect(0, 0, w, h); draw. FillRect(w, h, w, h); draw.dispose(); // Repeat the rendering if the target changed size } while (!size.

Equals(target.getSize())); } } interface Renderable { public Graphics acquireGraphics(); public Dimension getSize(); }.

That looks pretty neat. I shall try it out ASAP (which unfortunately may be Monday if I can't get to it tonight). A quick question though - the Renderable interface is just something locally defined, right?(No java.awt.

Renderable or similar seems to exist. ) – Charles Goodwin Aug 2 at 16:09 I won't be using a rootpane, as the custom UI we use takes over everything so it isn't necessary AFAICT. – Charles Goodwin Aug 2 at 16:13 1 The Renderable interface is defined as an inner class at the bottom of the file.It seemed to me using an interface was the best way to do it, as it provided the most flexibility to your implementation.

– Josh Aug 2 at 16:53 You did specify that No awt components were going to be added to the frame, correct? – Josh Aug 2 at 17:03 Correct - unless required to implement better rendering. :-) – Charles Goodwin Aug 2 at 17:04.

This answer is left here for reference, but is not the correct answer because it renders inside the EDT thread. Here is a working fix! :D Basically the problem is that the ComponentResized is not appropriately called until the mouse is released after a shrink.

Also, because the paint and checkSize methods are synchronized, they can exclude each other in rare instances. The fix is to override the validate method in the Frame class. This method is always called if the Frame changes state, including shrinks and growths.So we simply have to check the size in the validate and we can actually completely forget about using a ComponentResized method at all.

So, here is working code that compiles as is. I changed some of the variable names to improve my personal readability. Import java.awt.

Color; import java.awt. Dimension; import java.awt. Graphics; import java.awt.

Insets; import java.awt. Toolkit; import java.awt.image. BufferStrategy; import java.awt.

Frame; public class SmoothResize extends Frame { public static void main(String args) { Toolkit. GetDefaultToolkit(). SetDynamicLayout(true); System.

SetProperty("sun.awt. Noerasebackground", "true"); SmoothResize srtest = new SmoothResize(); //srtest. SetIgnoreRepaint(true); srtest.

SetSize(100, 100); srtest. SetVisible(true); } public SmoothResize() { render(); } private Dimension old_size = new Dimension(0, 0); private Dimension new_size = new Dimension(0, 0); public void validate() { super.validate(); new_size. Width = getWidth(); new_size.

Height = getHeight(); if (old_size. Equals(new_size)) { return; } else { render(); } } public void paint(Graphics g) { validate(); } public void update(Graphics g) { paint(g); } public void addNotify() { super.addNotify(); createBufferStrategy(2); } protected synchronized void render() { BufferStrategy strategy = getBufferStrategy(); if (strategy == null) { return; } // Render single frame do { // The following loop ensures that the contents of the drawing buffer // are consistent in case the underlying surface was recreated do { Graphics draw = strategy.getDrawGraphics(); Insets I = getInsets(); int w = (int)(((double)(getWidth() - i. Left - i.

Right))/2+0.5); int h = (int)(((double)(getHeight() - i. Top - i. Bottom))/2+0.5); draw.

SetColor(Color. YELLOW); draw. FillRect(i.

Left, i. Top + h, w,h); draw. FillRect(i.

Left + w, i. Top, w,h); draw. SetColor(Color.

BLACK); draw. FillRect(i. Left, i.

Top, w, h); draw. FillRect(i. Left + w, i.

Top + h, w,h); draw.dispose(); // Repeat the rendering if the drawing buffer contents // were restored } while (strategy. ContentsRestored()); // Display the buffer strategy.show(); // Repeat the rendering if the drawing buffer was lost } while (strategy.contentsLost()); } } I hope that works for you! Also, last second edit, I changed the logical ternary operation for the selection of your shrink or expand String.

The last comparison was unnecessary because for the comparison in question, the values can be greater than, less than or equal to each other. There is not another possibility that would not generate a NullPointerException. The stricken text is no longer relevant as I have completely removed that entire method.

I indicate the other changes I've made to the original post as comments.

Also, I'm not sure if this code was a grab from an actual in production code, but it might be advantageous to replace a method like checkSize(String s) with an ActionListener that listens to the frame itself. This would be more inline with the Java AWT Event model, and would provide a more consistent codebase. – Josh Aug 1 at 0:58 I have edited the original post again.

The extra MouseListener code was removed, as it served no purpose related to the question at hand. I also fixed the window flicker issue. That was do to implicit type conversion.

When you divided the int of the window's width and height by two in the render method, it initially converted them to doubles to hold the extra .5 it would get dividing odd numbers. For instance, the int window size 3 becomes 1.5 as a double. Putting a double value to an int variable converts through truncation, cutting off the .5, and leaving a little white line in the render.

– Josh Aug 1 at 8:10 And may I recommend that you utilize Swing components, like JFrame, instead of the outdated AWT classes? – Josh Aug 1 at 8:17 Your code didn't compile, there's an extra } ;-), but after removing that it works! Now I wonder what the difference is between using Swing and AWT for this, as there are no components added to the Frame/JFrame?

I'll post a follow up question for that, I think. – Charles Goodwin Aug 1 at 10:33 In retrospect I should have not given the +100 yet as this implementation does paint in the EDT which kinda breaks the model. It is synchronized, so it may work in the outside-EDT render model, and I'll check that and get back to you.

– Charles Goodwin Aug 1 at 10:48.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions