Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Standard Widget Toolkit (SWT) » Smoother Animation
Smoother Animation [message #455418] Fri, 13 May 2005 19:50 Go to next message
PB is currently offline PBFriend
Messages: 1
Registered: July 2009
Junior Member
I have written two snippets that perform a simple animation in SWT and
AWT. The AWT version uses the full screen mode and a page-flipping
BufferStrategy (the code doesn't actually force this, it just does this by
default on my h/w and WinXP - I've tried to keep the code minimal). The
SWT version resizes a Shell upto full screen and just paints. It
optionally double-buffers (a trivial copy operation is kept out of the
painting when double-buffering which probably doesn't save much under the
hood).

The AWT version is markedly smoother than the SWT version. In fact, the
SWT version is unusable. The code is as minimal as I could get it to show
the problem I have.

Can anyone suggest any changes to the SWT version to make the animation as
smooth as the AWT version? Do I have to go to OpenGL?

Thanks.

P.S. I've included the imports for the SWT version, as it uses both AWT
and SWT objects and obviously the import choice has to be right.

AWT version:
public class Viewer {
	Image bigImage;
	GraphicsDevice device;
	public static void main(String[] args) {
		new Viewer().run();
	}

	public void run() {
		GraphicsEnvironment env = GraphicsEnvironment
				.getLocalGraphicsEnvironment();
		device = env.getDefaultScreenDevice();
		GraphicsConfiguration gc = device.getDefaultConfiguration();		
		Frame frame = new Frame(gc);
		frame.setUndecorated(true);
		frame.setIgnoreRepaint(true);
		device.setFullScreenWindow(frame);
		frame.setVisible(true);
		Rectangle bounds = gc.getBounds();
		makeBigImage(frame, bounds);
		frame.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent arg0) {
				finish();
			}
		});				
		frame.createBufferStrategy(2);
		BufferStrategy bufferStrategy = frame.getBufferStrategy();
		
		int offsetX = 0;
		while (offsetX < bigImage.getWidth(frame) - bounds.width) {
			Graphics g = bufferStrategy.getDrawGraphics();
			if (!bufferStrategy.contentsLost()) {
				g.drawImage(bigImage, 0,
								0,
								bounds.width,
								bounds.height, offsetX, 0,
								offsetX + bounds.width,
								bounds.height, frame);			
				bufferStrategy.show();
				g.dispose();
				offsetX += 6;
			}
		}
	}
	
	private void finish() {
		device.setFullScreenWindow(null);
		System.exit(0);
	}

	private void makeBigImage(Frame frame, Rectangle bounds) {
		Point bigImageDims = new Point(bounds.width * 4, bounds.height);	
		bigImage = frame.createImage(bigImageDims.x, bigImageDims.y);
		GradientPaint gradient = new GradientPaint(0, 0, Color.red, 175, 175,
				Color.yellow, true);
		Graphics2D bigImageGraphics = (Graphics2D) bigImage.getGraphics();
		bigImageGraphics.setPaint(gradient);
		for (int x = 0; x < bigImageDims.x - 60; x += 60) {
			for (int y = 0; y < bigImageDims.y - 60; y += 60) {
				bigImageGraphics.fillOval(x, y, 50, 50);
			}
		}
		bigImageGraphics.dispose();		
	}
}


SWT version:
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class Viewer {
	Display display;

	Image bigImage, buffer;

	Rectangle screenSize;

	GC gc, bufferGC;
	
	boolean doubleBuffering;

	public static void main(String[] args) {
		new Viewer().run();
	}

	public void run() {
		
		doubleBuffering = true;
		
		display = Display.getDefault();
		Shell shell = new Shell(display, SWT.NO_BACKGROUND);		
		screenSize = display.getBounds();
		shell.setBounds(screenSize);
		shell.addMouseListener(new MouseAdapter() {
			public void mouseDoubleClick(MouseEvent arg0) {
				finish();
			}
		});

		shell.open();
		shell.forceFocus();
		gc = new GC(shell);
		makeBigImage();
		buffer = new Image(display, screenSize.width, screenSize.height);
		bufferGC = new GC(buffer);
		
		new MoveIt().start();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}

	}

	class MoveIt extends Thread {
		public void run() {
			int offset = 0;
			int stopAt = bigImage.getImageData().width - screenSize.width;
			while (offset < stopAt) {
				if (doubleBuffering) {
				bufferGC.drawImage(bigImage, offset += 3, 0, screenSize.width,
						screenSize.height, 0, 0, screenSize.width,
						screenSize.height);				
				gc.drawImage(buffer, 0, 0);
				}
				else {
					gc.drawImage(bigImage, offset += 3, 0, screenSize.width,
							screenSize.height, 0, 0, screenSize.width,
							screenSize.height);	
				}
			}
			finish();
		}
	}

	private void finish() {
		buffer.dispose();
		bigImage.dispose();
		gc.dispose();
		bufferGC.dispose();
		display.dispose();
		System.exit(0);
	}

	private void makeBigImage() {
		Point bigImageDims = new Point(screenSize.width * 4, screenSize.height);
		BufferedImage bufferedBigImage = new BufferedImage(bigImageDims.x,
				bigImageDims.y, BufferedImage.TYPE_INT_ARGB);
		GradientPaint gradient = new GradientPaint(0, 0, Color.red, 175, 175,
				Color.yellow, true);
		Graphics2D bigImageGraphics = (Graphics2D) bufferedBigImage
				.getGraphics();
		bigImageGraphics.setPaint(gradient);
		for (int x = 0; x < bigImageDims.x - 60; x += 60) {
			for (int y = 0; y < bigImageDims.y - 60; y += 60) {
				bigImageGraphics.fillOval(x, y, 50, 50);
			}
		}
		bigImageGraphics.dispose();

		// Stuff to convert AWT image to SWT image
		int[] data = ((DataBufferInt) bufferedBigImage.getRaster()
				.getDataBuffer()).getData();
		ImageData imageData = new ImageData(bigImageDims.x, bigImageDims.y, 32,
				new PaletteData(0xFF0000, 0xFF00,  0xFF));
		imageData.setPixels(0, 0, bigImageDims.x * bigImageDims.y, data, 0);
		bigImage = new Image(display, imageData);
	}
}
Re: Smoother Animation [message #455486 is a reply to message #455418] Mon, 16 May 2005 23:25 Go to previous messageGo to next message
Steve Northover is currently offline Steve NorthoverFriend
Messages: 1636
Registered: July 2009
Senior Member
So I played with your code a bit and found that the step size for the AWT
code was 6 while the SWT was 3. After changing this and getting rid of the
SWT double buffering, the times were closer (AWT was still somewhat faster).
If you run the code in a shell that is 512x512 rather than full screen, then
SWT was faster. For me, the AWT animation was jerky and the SWT animation
was smooth but perhaps we are looking at different things? The AWT one
paused slighty now and again. Could be my graphics card? So it seems that
switching to full screen mode rather than running in a shell is faster (not
much of a surprise there). Do you need to run in full screen mode?

"PB" <pbamford@gmail.com> wrote in message
news:640c9ea3b3b71d195ec50fbd2c18c185$1@www.eclipse.org...
> I have written two snippets that perform a simple animation in SWT and
> AWT. The AWT version uses the full screen mode and a page-flipping
> BufferStrategy (the code doesn't actually force this, it just does this by
> default on my h/w and WinXP - I've tried to keep the code minimal). The
> SWT version resizes a Shell upto full screen and just paints. It
> optionally double-buffers (a trivial copy operation is kept out of the
> painting when double-buffering which probably doesn't save much under the
> hood).
>
> The AWT version is markedly smoother than the SWT version. In fact, the
> SWT version is unusable. The code is as minimal as I could get it to show
> the problem I have.
>
> Can anyone suggest any changes to the SWT version to make the animation as
> smooth as the AWT version? Do I have to go to OpenGL?
>
> Thanks.
>
> P.S. I've included the imports for the SWT version, as it uses both AWT
> and SWT objects and obviously the import choice has to be right.
>
> AWT version:
>
> public class Viewer {
> Image bigImage;
> GraphicsDevice device;
> public static void main(String[] args) {
> new Viewer().run();
> }
>
> public void run() {
> GraphicsEnvironment env = GraphicsEnvironment
> .getLocalGraphicsEnvironment();
> device = env.getDefaultScreenDevice();
> GraphicsConfiguration gc = device.getDefaultConfiguration();
> Frame frame = new Frame(gc);
> frame.setUndecorated(true);
> frame.setIgnoreRepaint(true);
> device.setFullScreenWindow(frame);
> frame.setVisible(true);
> Rectangle bounds = gc.getBounds();
> makeBigImage(frame, bounds);
> frame.addMouseListener(new MouseAdapter() {
> public void mouseClicked(MouseEvent arg0) {
> finish();
> }
> });
> frame.createBufferStrategy(2);
> BufferStrategy bufferStrategy = frame.getBufferStrategy();
>
> int offsetX = 0;
> while (offsetX < bigImage.getWidth(frame) - bounds.width) {
> Graphics g = bufferStrategy.getDrawGraphics();
> if (!bufferStrategy.contentsLost()) {
> g.drawImage(bigImage, 0,
> 0,
> bounds.width,
> bounds.height, offsetX, 0,
> offsetX + bounds.width,
> bounds.height, frame);
> bufferStrategy.show();
> g.dispose();
> offsetX += 6;
> }
> }
> }
>
> private void finish() {
> device.setFullScreenWindow(null);
> System.exit(0);
> }
>
> private void makeBigImage(Frame frame, Rectangle bounds) {
> Point bigImageDims = new Point(bounds.width * 4, bounds.height);
> bigImage = frame.createImage(bigImageDims.x, bigImageDims.y);
> GradientPaint gradient = new GradientPaint(0, 0, Color.red, 175, 175,
> Color.yellow, true);
> Graphics2D bigImageGraphics = (Graphics2D) bigImage.getGraphics();
> bigImageGraphics.setPaint(gradient);
> for (int x = 0; x < bigImageDims.x - 60; x += 60) {
> for (int y = 0; y < bigImageDims.y - 60; y += 60) {
> bigImageGraphics.fillOval(x, y, 50, 50);
> }
> }
> bigImageGraphics.dispose();
> }
> }
> 

>
> SWT version:
>
> import java.awt.Color;
> import java.awt.GradientPaint;
> import java.awt.Graphics2D;
> import java.awt.image.BufferedImage;
> import java.awt.image.DataBufferInt;
>
> import org.eclipse.swt.SWT;
> import org.eclipse.swt.events.MouseAdapter;
> import org.eclipse.swt.events.MouseEvent;
> import org.eclipse.swt.graphics.GC;
> import org.eclipse.swt.graphics.Image;
> import org.eclipse.swt.graphics.ImageData;
> import org.eclipse.swt.graphics.PaletteData;
> import org.eclipse.swt.graphics.Point;
> import org.eclipse.swt.graphics.Rectangle;
> import org.eclipse.swt.widgets.Display;
> import org.eclipse.swt.widgets.Shell;
>
> public class Viewer {
> Display display;
>
> Image bigImage, buffer;
>
> Rectangle screenSize;
>
> GC gc, bufferGC;
>
> boolean doubleBuffering;
>
> public static void main(String[] args) {
> new Viewer().run();
> }
>
> public void run() {
>
> doubleBuffering = true;
>
> display = Display.getDefault();
> Shell shell = new Shell(display, SWT.NO_BACKGROUND);
> screenSize = display.getBounds();
> shell.setBounds(screenSize);
> shell.addMouseListener(new MouseAdapter() {
> public void mouseDoubleClick(MouseEvent arg0) {
> finish();
> }
> });
>
> shell.open();
> shell.forceFocus();
> gc = new GC(shell);
> makeBigImage();
> buffer = new Image(display, screenSize.width, screenSize.height);
> bufferGC = new GC(buffer);
>
> new MoveIt().start();
> while (!shell.isDisposed()) {
> if (!display.readAndDispatch())
> display.sleep();
> }
>
> }
>
> class MoveIt extends Thread {
> public void run() {
> int offset = 0;
> int stopAt = bigImage.getImageData().width - screenSize.width;
> while (offset < stopAt) {
> if (doubleBuffering) {
> bufferGC.drawImage(bigImage, offset += 3, 0, screenSize.width,
> screenSize.height, 0, 0, screenSize.width,
> screenSize.height);
> gc.drawImage(buffer, 0, 0);
> }
> else {
> gc.drawImage(bigImage, offset += 3, 0, screenSize.width,
> screenSize.height, 0, 0, screenSize.width,
> screenSize.height);
> }
> }
> finish();
> }
> }
>
> private void finish() {
> buffer.dispose();
> bigImage.dispose();
> gc.dispose();
> bufferGC.dispose();
> display.dispose();
> System.exit(0);
> }
>
> private void makeBigImage() {
> Point bigImageDims = new Point(screenSize.width * 4, screenSize.height);
> BufferedImage bufferedBigImage = new BufferedImage(bigImageDims.x,
> bigImageDims.y, BufferedImage.TYPE_INT_ARGB);
> GradientPaint gradient = new GradientPaint(0, 0, Color.red, 175, 175,
> Color.yellow, true);
> Graphics2D bigImageGraphics = (Graphics2D) bufferedBigImage
> .getGraphics();
> bigImageGraphics.setPaint(gradient);
> for (int x = 0; x < bigImageDims.x - 60; x += 60) {
> for (int y = 0; y < bigImageDims.y - 60; y += 60) {
> bigImageGraphics.fillOval(x, y, 50, 50);
> }
> }
> bigImageGraphics.dispose();
>
> // Stuff to convert AWT image to SWT image
> int[] data = ((DataBufferInt) bufferedBigImage.getRaster()
> .getDataBuffer()).getData();
> ImageData imageData = new ImageData(bigImageDims.x, bigImageDims.y, 32,
> new PaletteData(0xFF0000, 0xFF00,  0xFF));
> imageData.setPixels(0, 0, bigImageDims.x * bigImageDims.y, data, 0);
> bigImage = new Image(display, imageData);
> }
> }
> 

>
>
>
>
>
Re: Smoother Animation [message #455597 is a reply to message #455486] Tue, 17 May 2005 21:55 Go to previous message
Pascal Bamford is currently offline Pascal BamfordFriend
Messages: 1
Registered: July 2009
Junior Member
Thanks for taking the time to try the code.

The step size was a hack to make both animations run at a similar speed on
my h/w - I should have highlighted that, sorry. I didn't want to riddle
the code with timers etc.

I'm not looking at 'frame rate' here. The SWT version definitely has a
higher frame rate for whatever reason. It is the jerkiness that's the
problem. Interesting that you found the AWT version more jerky. Clearly
there is a hardware factor here.

Either way, I've tested both versions on many high and low end graphics
cards and PCs and for what I need, the page-flipping AWT version is
clearly smoother (I think that the use of timers will fix the occasional
pause in motion). The synthetic image probably doesn't show up the issue
as well as I'd have liked.

The conclusion I've got to so far, with messing around with many versions
of AWT and SWT code, is that page-flipping is the only option that really
gives good animation at high speed (this is probably a 'duh' for some).
Just wondering whether anyone has tried to write some fast animation in
SWT and found similar issues/solutions...
Previous Topic:GUI SWT Designer for Mac OS X
Next Topic:Problem using fillRoundRectangle and setClipping
Goto Forum:
  


Current Time: Fri Apr 26 09:57:20 GMT 2024

Powered by FUDForum. Page generated in 0.02644 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top