JPanel distorted scaling issue - java

Description: I am writing a small program that needs to generate a report (1 pager). This is nothing big and it's the first time I need to generate some sort of report as a printable output. Should be simple enough, so I created a JPanel, added all the fields/panels and styles required to make it look like a report.
Problem: When I try to print the report it does not fit on an A4 and is cuts off at the right and bottom. I then tried to change the print method to scale the JPanel but now I am getting some strange compression (right word?) issues on the font and some other items.
What I've tried: I tried to print the report to a JPEG/PNG (This looks perfect when viewed) and then send to the printer but this causes horrible image quality issues. I then changed the JPanel contents to be smaller to fit but this made the report look to small when viewed on the screen before printing.
Help with: It would be nice if someone could point me in the right direction or tell me where my scaling is causing the issue if possible... I really do not look forward to creating different panels for each report just to view and print correctly.
public int print(Graphics gc, PageFormat pageFormat, int pageIndex) {
if(pageIndex>0) {
return NO_SUCH_PAGE;
}
// Create a instance of the RepaintManager from the component being printed
RepaintManager mgr = RepaintManager.currentManager(component);
Graphics2D g2d = (Graphics2D)gc;
// Get the bounds of the component
Dimension dim = component.getSize();
double cHeight = dim.getHeight();
double cWidth = dim.getWidth();
// Get the bounds of the printable area
double pHeight = pageFormat.getImageableHeight();
double pWidth = pageFormat.getImageableWidth();
double pXStart = pageFormat.getImageableX();
double pYStart = pageFormat.getImageableY();
double xRatio = pWidth / cWidth;
double yRatio = pHeight / cHeight;
g2d.scale(xRatio, yRatio);
mgr.setDoubleBufferingEnabled(false); // Only for swing components
component.paint(g2d);
mgr.setDoubleBufferingEnabled(true); // Only for swing components
return PAGE_EXISTS;}

Related

Is cropping and rescaling background a good solution for java games?

I'm very new to java and I'm currently developping a 2D game.
I'm trying to use Java Swing for the graphics and I have a problem doing so :
Displaying the background, which is a fairly high definition image, (currently 2000x2000 but will grow bigger for higher definition), with a map of 50 units in width and height.
The problem is that I don't want to display the whole map but only a fixed amount of cells in width and height of it (here i chose 20). I first tried to rescale the image wider than the screen to make the 20 cells fit perfectly (a bit like a zoom on the area we want) and then draw it with an offset related to the player's position (which is always displayed on the centered of the screen).
But while i try to go with bigger images, i get a java heap space memory exception.
So i was thinking of getting a cropped version of the image and then rescale it to the screen's dimension to have a smaller rescaled image. I'm not getting exceptions any more but I have some important performances issues with a drop of 30 fps.
I was also thinking about getting all cropped images possible and storing them but I wanted to know if that's a thing or not.
To sum up, I was wondering what were the best ways to display a background in games.
Since 2D games or even 3D games have maps even larger than I do, I think I must be missing something, I don't get how to display sprites with high resolution while keeping a decent frame rate.
Thank your for your time.
edit:
To put a bit of context : The map is a big maze and the player should only be able to see a local view of the maze. And because I would want a rather detailed Background, i have to be able to display large images.
Here is a reduced view of my code sample :
public class Background implements Drawable, Anchor {
private final String name;
private final Image image;
private final int width;
public Background(String name){
this.name = name;
BufferedImage image = FileSystem.readBufferedImage(GraphicType.BACKGROUND, name);
//image is a 2000x2000 image
this.image = image.getScaledInstance((int)(behavior.width()
* (Game.frame.getWidth()/(double) Settings.NB_CELLS_ON_SCREEN_WIDTH)),
-1,
0
);
//result in a 19200x19200 image
this.width = (int)(behavior.width()
* (Game.frame.getWidth()/(double)Settings.NB_CELLS_ON_SCREEN_WIDTH));
}
#Override
public void draw(Graphics g) {
g.drawImage(
image,
-8640,
-9060,
null);
}
}
With the GraphicPosition class computing the position on screen, with the following arguments in constructor : An anchor object, an xOffset and a yOffset
I now draw the background using the drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer)
As matt suggested, it causes a less significant fps drop because i'm no longer creating a huge temporary image and the good thing about this solution is that the difference in frame rate with bigger images seems to be small.
Here is the code I used and worked for me :
public class Foreground implements Drawable {
private final String name;
private final BufferedImage image;
private final Behavior behavior;
private final int width;
public Foreground(String name, Behavior behavior){
this.name = name;
this.image = FileSystem.readBufferedImage(GraphicType.FOREGROUND, name);
this.behavior = behavior;
}
#Override
public void draw(Graphics g) {
/*This variable represents the width on the image of the number of cells
In my code its is the width on the image of 20 cells*/
int widthOnImageForNbCellsDisplayed = (image.getWidth()/behavior.width()) * Settings.NB_CELLS_ON_SCREEN_WIDTH;
/*This posXInImage represents the position of the top left corner of the
area of the image we want to draw*/
int posXInImage = (int)(
Game.player.posX()
* image.getWidth()
/ (double)behavior.width()
- widthOnImageForNbCellsDisplayed/2
);
int posYInImage = (int)(
Game.player.posY()
* image.getHeight()
/ (double)behavior.height()
- widthOnImageForNbCellsDisplayed/2
);
/*Here is struggled with the fact that the position of the second
coordinates is absolute and not relative to the first coordinates
,what I was originally thinking*/
g.drawImage(image,
0,
-(Game.frame.getWidth() - Game.frame.getHeight())/2,
Game.frame.getWidth(),
Game.frame.getWidth()-(Game.frame.getWidth() - Game.frame.getHeight())/2,
posXInImage,
posYInImage,
posXInImage + widthOnImageForNbCellsDisplayed,
posYInImage + widthOnImageForNbCellsDisplayed,
null);
}
}

FPS drops after loading images in java

So, I recently asked a question on how to preload images in Java (preloading images in Java) and it worked great! Until I went to play the game. Framerate dropped drastically. I don't know what it was, but basically, I have a whole sprite map loaded into an array. Each image corresponds to a three-degree rotation. So, 5 degrees would become the 3-degree image, 6 would stay the 6, and so on (I tried Math.round and it actually made the 5 and 4-degree images go to the 6-degree image, and that's more desirable, however, it's slower)
I am looking for some ways to optimize the code. Here are my angle calculations:
private float getAngle(double x, double y) {
float angle = (float) Math.toDegrees(Math.atan2(y - this.getCenterY(), x - this.getCenterX()));
if(angle < 0){
angle += 360;
}
return angle;
}
The x and y values inputted into the method are the center x and y values of the enemy being targeted by the tower performing this calculation. Then this code is executed in the draw method:
if(airID==Value.towerCannon && (airRow>0 && airRow<5) && angle>=0) {
if(angle==Canvas.rotatedAirMap.length) angle = 0;
g.drawImage(Canvas.rotatedAirMap[angle][level-1], x, y, width, height, null);
} else {
g.drawImage(Canvas.airMap[airRow][airID], x, y, width, height, null);
}
}
This will draw the appropriate, preloaded image rotated at the specified angle (The "angle" - or image identifier - is calculated when the tower shoots by dividing the result of the angle calculation by three and then casting that to an int - I could also round that value)
Any suggestions on how to optimize this so I don't get such massive frame drops? I assume the frame drops are due to the VM heap size being too small, but I've increased it and still, nothing significant happens. Any help would be greatly appreciated.
Thanks!
#VGR here is what I did with your response:
public void paintComponent(Graphics g) {
if(isFirst) { //Define stuff when isFirst is true
define(); //Sets up the image arrays
GraphicsConfiguration config = getGraphicsConfiguration();
if(config == null) {
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
config = env.getDefaultScreenDevice().getDefaultConfiguration();
}
BufferedImage compatibleImage = config.createCompatibleImage(image.getWidth(), image.getHeight(), image.getTransparency());
g = compatibleImage.createGraphics();
isFirst = false;
}
}
This works a little bit faster, but I had to do some workarounds. repaint() is called in the game loop (this class implements runnable) So the graphics component created by the repaint method (however that works) is the graphics I use for the whole game. Would this be the correct way to do it?
Translating images from their inherent color model to the color model of the current video mode can slow down rendering. To avoid this, you can make sure each image is compatible with the screen where your window resides:
BufferedImage image = ImageIO.read(/* ... */);
GraphicsConfiguration config = getGraphicsConfiguration();
if (config == null) {
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment;
config = env.getDefaultScreenDevice().getDefaultConfiguration();
}
BufferedImage compatibleImage = config.createCompatibleImage(
image.getWidth(), image.getHeight(), image.getTransparency());
Graphics2D g = compatibleImage.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
image = compatibleImage;
If an image has the same color model as the current video mode, there is no translation needed when drawing it. It’s even possible that painting of such an image may be done entirely by the GPU.

OutOfMemoryError: Jave heap space when jtable saved as Image

Currently I am saving a jtable as jpeg using the below method, when the dimension of the jtable became 2590, 126181, java.lang.OutOfMemoryError: Java heap space exception occurs at "BufferedImage constructor", when the size of the table is small the image gets saved successfully.
public BufferedImage saveComponentAsJPEG(JTable table, String filename) {
Dimension size = table.getSize();
BufferedImage myImage =
new BufferedImage(size.width, size.height,
BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = myImage.createGraphics();
table.paint(g2);
return myImage;
}
How to save a jtable with bigger size in pdf or jpeg image?
Updated Info:
You asked how to "split the JTable into different small images":
As you go through my code below please read my comments, they help explain what is happening and will help you grasp a better understanding of how a JTable/JComponent can be painted to lots of small images. At the heart my code is similar to yours, but there are two key points:
1) Rather than create a single large BufferedImage, I create a single small image that is then used multiple times, therefore leaving a very small memory footprint.
2) With the single image, I use Graphics.translate() to paint a small part of the JTable each time.
The following code was tested with a large JComponents (2590 x 126181) and a tile size of 200x200, and the whole process did not exceed 60mb of memory:
//width = width of tile in pixels, for minimal memory usage try 200
//height = height of tile in pixels, for minimal memory usage try 200
//saveFileLocation = folder to save image tiles
//component = The JComponent to save as tiles
public static boolean saveComponentTiles(int width, int height, String saveFileLocation, JComponent component)
{
try
{
//Calculate tile sizes
int componentWidth = component.getWidth();
int componentHeight = component.getHeight();
int horizontalTiles = (int) Math.ceil((double)componentWidth / width); //use (double) so Math.ceil works correctly.
int verticalTiles = (int) Math.ceil((double)componentHeight / height); //use (double) so Math.ceil works correctly.
System.out.println("Tiles Required (H, W): "+horizontalTiles+", verticalTiles: "+verticalTiles);
//preset arguments
BufferedImage image;
//Loop through vertical and horizontal tiles
//Draw part of the component to the image
//Save image to file
for (int h = 0; h < verticalTiles; h++)
{
for (int w = 0; w < horizontalTiles; w++)
{
//check tile size, if area to paint is smaller than image then shrink image
int imageHeight = height;
int imageWidth = width;
if (h + 1 == verticalTiles)
{
imageHeight = componentHeight - (h * height);
}
if (w + 1 == horizontalTiles)
{
imageWidth = componentWidth - (w * width);
}
image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_ARGB);
Graphics g = image.getGraphics();
//translate image graphics so that only the correct part of the component is panted to the image
g.translate(-(w * width), -(h * height));
component.paint(g);
//In my example I am saving the image to file, however you could throw your PDF processing code here
//Files are named as "Image.[h].[w]"
//Example: Image 8 down and 2 accross would save as "Image.8.2.png"
ImageIO.write(image, "png", new File(saveFileLocation + "Image." + h +"."+ w + ".png"));
//tidy up
g.dispose();
}
}
return true;
}
catch (IOException ex)
{
return false;
}
}
Just call it like so:
boolean result = saveComponentTiles(200, 200, saveFileLocation, jTable1);
Also if you haven't done it already, you should only call the method from a different thread because it will hang your application when dealing with large components.
If you have not picked a PDF library yet, then I highly recommend looking at iText.
Original Post:
The process you are looking for is quite simple, however it may take some work.
You were on the right track thinking about parts, but as David
mentioned you shouldn't mess with the jTable, instead you will need a
to make use of the TiledImage class, or do something yourself with
RenderedImage and Rasters.
This sort of method basically uses HDD space instead of memory and
lets you create a large image in lots of smaller parts/tiles, then
when its done you can save it all to a single image file.
This answer may also help: https://stackoverflow.com/a/14069551/1270000

Does Java Graphics (Graphics2D) uses graphics card? [duplicate]

I'm having performance oddities with Java2D. I know of the sun.java2d.opengl VM parameter to enable 3D acceleration for 2D, but even using that has some weird issues.
Here are results of tests I ran:
Drawing a 25x18 map with 32x32 pixel tiles on a JComponent
Image 1 = .bmp format, Image 2 = A .png format
Without -Dsun.java2d.opengl=true
120 FPS using .BMP image 1
13 FPS using .PNG image 2
With -Dsun.java2d.opengl=true
12 FPS using .BMP image 1
700 FPS using .PNG image 2
Without acceleration, I'm assuming some kind of transformation is taking place with every drawImage() I do in software, and is pulling down the FPS considerably in the case of .PNG. Why though, with acceleration, would the results switch (and PNG actually performs incredibly faster)?! Craziness!
.BMP Image 1 is translated to an image type of TYPE_INT_RGB. .PNG Image 2 is translated to an image type of TYPE_CUSTOM. In order to get consistent speed with and without opengl acceleration, I have to create a new BufferedImage with an image type of TYPE_INT_ARGB, and draw Image 1 or Image 2 to this new image.
Here are the results running with that:
Without -Dsun.java2d.opengl=true
120 FPS using .BMP image 1
120 FPS using .PNG image 2
With -Dsun.java2d.opengl=true
700 FPS using .BMP image 1
700 FPS using .PNG image 2
My real question is, can I assume that TYPE_INT_ARGB will be the native image type for all systems and platforms? I'm assuming this value could be different. Is there some way for me to get the native value so that I can always create new BufferedImages for maximum performance?
Thanks in advance...
I think I found a solution by researching and putting bits and pieces together from too many Google searches.
Here it is, comments and all:
private BufferedImage toCompatibleImage(BufferedImage image)
{
// obtain the current system graphical settings
GraphicsConfiguration gfxConfig = GraphicsEnvironment.
getLocalGraphicsEnvironment().getDefaultScreenDevice().
getDefaultConfiguration();
/*
* if image is already compatible and optimized for current system
* settings, simply return it
*/
if (image.getColorModel().equals(gfxConfig.getColorModel()))
return image;
// image is not optimized, so create a new image that is
BufferedImage newImage = gfxConfig.createCompatibleImage(
image.getWidth(), image.getHeight(), image.getTransparency());
// get the graphics context of the new image to draw the old image on
Graphics2D g2d = newImage.createGraphics();
// actually draw the image and dispose of context no longer needed
g2d.drawImage(image, 0, 0, null);
g2d.dispose();
// return the new optimized image
return newImage;
}
In my previous post, GraphicsConfiguration was what held the information needed to create optimized images on a system. It seems to work pretty well, but I would have thought Java would automatically do this for you. Obviously you can't get too comfortable with Java. :) I guess I ended up answering my own question. Oh well, hopefully it'll help some of you I've seen trying to make use of Java for 2D games.
Well, this is old post but I'd like to share my findings about direct drawing with Swing/AWT, without BufferedImage.
Some kind of drawing, as 3D, are better done when painting directly to a int[] buffer. Once done the images, you can use an ImageProducer instance, like MemoryImageSource, to produce images. I'm assuming you know how to perform your drawings directly, without help of Graphics/Graphics2.
/**
* How to use MemoryImageSource to render images on JPanel
* Example by A.Borges (2015)
*/
public class MyCanvas extends JPanel implements Runnable {
public int pixel[];
public int width;
public int height;
private Image imageBuffer;
private MemoryImageSource mImageProducer;
private ColorModel cm;
private Thread thread;
public MyCanvas() {
super(true);
thread = new Thread(this, "MyCanvas Thread");
}
/**
* Call it after been visible and after resizes.
*/
public void init(){
cm = getCompatibleColorModel();
width = getWidth();
height = getHeight();
int screenSize = width * height;
if(pixel == null || pixel.length < screenSize){
pixel = new int[screenSize];
}
mImageProducer = new MemoryImageSource(width, height, cm, pixel,0, width);
mImageProducer.setAnimated(true);
mImageProducer.setFullBufferUpdates(true);
imageBuffer = Toolkit.getDefaultToolkit().createImage(mImageProducer);
if(thread.isInterrupted() || !thread.isAlive()){
thread.start();
}
}
/**
* Do your draws in here !!
* pixel is your canvas!
*/
public /* abstract */ void render(){
// rubisch draw
int[] p = pixel; // this avoid crash when resizing
if(p.length != width * height) return;
for(int x=0; x < width; x++){
for(int y=0; y<height; y++){
int color = (((x + i) % 255) & 0xFF) << 16; //red
color |= (((y + j) % 255) & 0xFF) << 8; //green
color |= (((y/2 + x/2 - j) % 255) & 0xFF) ; //blue
p[ x + y * width] = color;
}
}
i += 1;
j += 1;
}
private int i=1,j=256;
#Override
public void run() {
while (true) {
// request a JPanel re-drawing
repaint();
try {Thread.sleep(5);} catch (InterruptedException e) {}
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
// perform draws on pixels
render();
// ask ImageProducer to update image
mImageProducer.newPixels();
// draw it on panel
g.drawImage(this.imageBuffer, 0, 0, this);
}
/**
* Overrides ImageObserver.imageUpdate.
* Always return true, assuming that imageBuffer is ready to go when called
*/
#Override
public boolean imageUpdate(Image image, int a, int b, int c, int d, int e) {
return true;
}
}// end class
Note we need unique instance of MemoryImageSource and Image. Do not create new Image or new ImageProducer for each frames, unless you have resized your JPanel. See init() method above.
In a rendering thread, ask a repaint(). On Swing, repaint() will call the overridden paintComponent(), where it call your render() method and then ask your imageProducer to update image.
With Image done, draw it with Graphics.drawImage().
To have a compatible Image, use proper ColorModel when you create your Image. I use GraphicsConfiguration.getColorModel():
/**
* Get Best Color model available for current screen.
* #return color model
*/
protected static ColorModel getCompatibleColorModel(){
GraphicsConfiguration gfx_config = GraphicsEnvironment.
getLocalGraphicsEnvironment().getDefaultScreenDevice().
getDefaultConfiguration();
return gfx_config.getColorModel();
}
From what I remember when I was thinking about doing graphics programming in Java, the built in libraries are slow. I was advised on GameDev.Net that anyone doing anything serious would have to use something like jogl

Java2D Performance Issues

I'm having performance oddities with Java2D. I know of the sun.java2d.opengl VM parameter to enable 3D acceleration for 2D, but even using that has some weird issues.
Here are results of tests I ran:
Drawing a 25x18 map with 32x32 pixel tiles on a JComponent
Image 1 = .bmp format, Image 2 = A .png format
Without -Dsun.java2d.opengl=true
120 FPS using .BMP image 1
13 FPS using .PNG image 2
With -Dsun.java2d.opengl=true
12 FPS using .BMP image 1
700 FPS using .PNG image 2
Without acceleration, I'm assuming some kind of transformation is taking place with every drawImage() I do in software, and is pulling down the FPS considerably in the case of .PNG. Why though, with acceleration, would the results switch (and PNG actually performs incredibly faster)?! Craziness!
.BMP Image 1 is translated to an image type of TYPE_INT_RGB. .PNG Image 2 is translated to an image type of TYPE_CUSTOM. In order to get consistent speed with and without opengl acceleration, I have to create a new BufferedImage with an image type of TYPE_INT_ARGB, and draw Image 1 or Image 2 to this new image.
Here are the results running with that:
Without -Dsun.java2d.opengl=true
120 FPS using .BMP image 1
120 FPS using .PNG image 2
With -Dsun.java2d.opengl=true
700 FPS using .BMP image 1
700 FPS using .PNG image 2
My real question is, can I assume that TYPE_INT_ARGB will be the native image type for all systems and platforms? I'm assuming this value could be different. Is there some way for me to get the native value so that I can always create new BufferedImages for maximum performance?
Thanks in advance...
I think I found a solution by researching and putting bits and pieces together from too many Google searches.
Here it is, comments and all:
private BufferedImage toCompatibleImage(BufferedImage image)
{
// obtain the current system graphical settings
GraphicsConfiguration gfxConfig = GraphicsEnvironment.
getLocalGraphicsEnvironment().getDefaultScreenDevice().
getDefaultConfiguration();
/*
* if image is already compatible and optimized for current system
* settings, simply return it
*/
if (image.getColorModel().equals(gfxConfig.getColorModel()))
return image;
// image is not optimized, so create a new image that is
BufferedImage newImage = gfxConfig.createCompatibleImage(
image.getWidth(), image.getHeight(), image.getTransparency());
// get the graphics context of the new image to draw the old image on
Graphics2D g2d = newImage.createGraphics();
// actually draw the image and dispose of context no longer needed
g2d.drawImage(image, 0, 0, null);
g2d.dispose();
// return the new optimized image
return newImage;
}
In my previous post, GraphicsConfiguration was what held the information needed to create optimized images on a system. It seems to work pretty well, but I would have thought Java would automatically do this for you. Obviously you can't get too comfortable with Java. :) I guess I ended up answering my own question. Oh well, hopefully it'll help some of you I've seen trying to make use of Java for 2D games.
Well, this is old post but I'd like to share my findings about direct drawing with Swing/AWT, without BufferedImage.
Some kind of drawing, as 3D, are better done when painting directly to a int[] buffer. Once done the images, you can use an ImageProducer instance, like MemoryImageSource, to produce images. I'm assuming you know how to perform your drawings directly, without help of Graphics/Graphics2.
/**
* How to use MemoryImageSource to render images on JPanel
* Example by A.Borges (2015)
*/
public class MyCanvas extends JPanel implements Runnable {
public int pixel[];
public int width;
public int height;
private Image imageBuffer;
private MemoryImageSource mImageProducer;
private ColorModel cm;
private Thread thread;
public MyCanvas() {
super(true);
thread = new Thread(this, "MyCanvas Thread");
}
/**
* Call it after been visible and after resizes.
*/
public void init(){
cm = getCompatibleColorModel();
width = getWidth();
height = getHeight();
int screenSize = width * height;
if(pixel == null || pixel.length < screenSize){
pixel = new int[screenSize];
}
mImageProducer = new MemoryImageSource(width, height, cm, pixel,0, width);
mImageProducer.setAnimated(true);
mImageProducer.setFullBufferUpdates(true);
imageBuffer = Toolkit.getDefaultToolkit().createImage(mImageProducer);
if(thread.isInterrupted() || !thread.isAlive()){
thread.start();
}
}
/**
* Do your draws in here !!
* pixel is your canvas!
*/
public /* abstract */ void render(){
// rubisch draw
int[] p = pixel; // this avoid crash when resizing
if(p.length != width * height) return;
for(int x=0; x < width; x++){
for(int y=0; y<height; y++){
int color = (((x + i) % 255) & 0xFF) << 16; //red
color |= (((y + j) % 255) & 0xFF) << 8; //green
color |= (((y/2 + x/2 - j) % 255) & 0xFF) ; //blue
p[ x + y * width] = color;
}
}
i += 1;
j += 1;
}
private int i=1,j=256;
#Override
public void run() {
while (true) {
// request a JPanel re-drawing
repaint();
try {Thread.sleep(5);} catch (InterruptedException e) {}
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
// perform draws on pixels
render();
// ask ImageProducer to update image
mImageProducer.newPixels();
// draw it on panel
g.drawImage(this.imageBuffer, 0, 0, this);
}
/**
* Overrides ImageObserver.imageUpdate.
* Always return true, assuming that imageBuffer is ready to go when called
*/
#Override
public boolean imageUpdate(Image image, int a, int b, int c, int d, int e) {
return true;
}
}// end class
Note we need unique instance of MemoryImageSource and Image. Do not create new Image or new ImageProducer for each frames, unless you have resized your JPanel. See init() method above.
In a rendering thread, ask a repaint(). On Swing, repaint() will call the overridden paintComponent(), where it call your render() method and then ask your imageProducer to update image.
With Image done, draw it with Graphics.drawImage().
To have a compatible Image, use proper ColorModel when you create your Image. I use GraphicsConfiguration.getColorModel():
/**
* Get Best Color model available for current screen.
* #return color model
*/
protected static ColorModel getCompatibleColorModel(){
GraphicsConfiguration gfx_config = GraphicsEnvironment.
getLocalGraphicsEnvironment().getDefaultScreenDevice().
getDefaultConfiguration();
return gfx_config.getColorModel();
}
From what I remember when I was thinking about doing graphics programming in Java, the built in libraries are slow. I was advised on GameDev.Net that anyone doing anything serious would have to use something like jogl

Categories