Gif is not animating through buffered image - java

I am working on a project in which I need to create graphics (bufferedimage) on another image.
I am using ZK framework for Front end and java for back end.
Here is my sample code and output.
public void createImage() throws Exception{
ladleList = fD.getListLocation();
baseImage = ImageIO.read(new File(BASE_IMG));
Graphics2D baseGraphics = baseImage.createGraphics();
for(LtsLadleLocation ladLoc : ladleList){
setLadlePostion(ladLoc);
setLadleImage(ladle);
Graphics2D imageGraphics = ladleImage.createGraphics();
imageGraphics.setFont(font);
String ladleNo = ladle.getLadleId().intValue() <=9 ? " "+ladle.getLadleId().toString() : ladle.getLadleId().toString();
imageGraphics.drawString(ladleNo, 12, 45);
baseGraphics.drawImage(ladleImage, position.getxVal(), position.getyVal(), 62,62,null,null);
img.setContent(baseImage);
BindUtils.postNotifyChange(null, null, this, "img");
ladle=null;
position = null;
ladleImage = null;
}
}
/**
* #Desc : selects the ladle and position values from the Position List.
* posList is having x and y values for particular locations.
* #param : ladLoc and position
*/
public void setLadlePostion(LtsLadleLocation ladLoc) {
for(Position pos:posList){
if(ladLoc.getLocationdescription().equalsIgnoreCase(pos.getLocName())){
ladle = ladLoc;
position = pos;
break;
}
}
}
/**
* #Desc : This method is used to get the relevent image according to the location
* and according to the status.
* #param ladle2
*/
public void setLadleImage(LtsLadleLocation ladleImageObj) throws Exception {
if("LF_2".equalsIgnoreCase(ladleImageObj.getLocationdescription())){
setLFLadle(ladleImageObj);
}else{
setNormalLadle(ladleImageObj);
}
}
/**
* #Desc : This method is used to set the normal ladle images (Circle Shaped images)
* #param ladleImageObj
*/
public void setNormalLadle(LtsLadleLocation ladleImageObj) throws Exception {
if("OUT".equalsIgnoreCase(ladleImageObj.getStatus())){
ladleImage = ImageIO.read(new File(HEATER_OUT));
}else if("IN".equalsIgnoreCase(ladleImageObj.getStatus())){
if("F".equalsIgnoreCase(ladleImageObj.getLadleStatusFlag())){
ladleImage = ImageIO.read(new File(HEATER_FILLED));
}else{
ladleImage = ImageIO.read(new File(HEATER_EMPTY));
}
}
}
/**
* #Desc : For Setting LF images
* #param ladleImageObj
*/
public void setLFLadle(LtsLadleLocation ladleImageObj) throws Exception {
if("OUT".equalsIgnoreCase(ladleImageObj.getStatus())){
ladleImage = ImageIO.read(new File(LADLE_OUT));
}else if("IN".equalsIgnoreCase(ladleImageObj.getStatus())){
if("F".equalsIgnoreCase(ladleImageObj.getLadleStatusFlag())){
ladleImage = ImageIO.read(new File(LADLE_FILLED));
}else{
ladleImage = ImageIO.read(new File(LADLE_EMPTY));
}
}
}
Where img is an element id of ZK element Image.
and my ZK code is
<window title="Hello World!!" border="normal" apply="org.zkoss.bind.BindComposer"
viewModel = "#id('vm') #init('com.practice.image.ImageViewModel')">
<image id="img" >
<custom-attributes org.zkoss.zul.image.preload="true" />
</image>
<timer id="refresh" repeats="true" onTimer="#command('createImage')" delay="10000"/>
</window>
I need to have GIF image(blinking image) on ladle 7. but its not animating please help me through this.
The output is as followsenter image description here

Related

Java Batik resize SVG to panel size keeping aspect ratio

I'm trying to display an SVG Image on my swing application,
since i don't have an SVG file but a path i'm converting the path to a valid svg document with:
private static Document buildSVGDocument(Color svgColor, /*double svgWidth, double svgHeight,*/ String svgPath) {
DOMImplementation svgDocumentImplementation = SVGDOMImplementation.getDOMImplementation();
Document svgDocument = svgDocumentImplementation.createDocument(SVGDOMImplementation.SVG_NAMESPACE_URI, "svg", null);
Element svgDocumentElement = svgDocument.getDocumentElement();
//svgDocumentElement.setAttribute("height", String.valueOf(svgHeight));
//svgDocumentElement.setAttribute("width", String.valueOf(svgWidth));
Element svgDocumentPath = svgDocument.createElementNS(SVGDOMImplementation.SVG_NAMESPACE_URI, "path");
svgDocumentPath.setAttribute("style", String.format("fill:rgb(%s, %s, %s);", svgColor.getRed(), svgColor.getGreen(), svgColor.getBlue()));
svgDocumentPath.setAttribute("d", svgPath);
svgDocumentElement.appendChild(svgDocumentPath);
return svgDocument;
}
Then I display the SVG Document on a Batik Canvas:
JSVGCanvas panel = new JSVGCanvas();
panel.setDocumentState(JSVGCanvas.ALWAYS_DYNAMIC);
panel.setDisableInteractions(true);
panel.setDocument(buildSVGDocument(/*etc*/));
container.add(panel, BorderLayout.WEST);
Now my question is: how do I resize the svg to the panel size keeping the aspect-ratio?
I figured out how to do it!,
Browsing the source I found the method used to calculate the image scale, it's:
calculateViewingTransform
Then I've implemented a simple class to scale the image to the container
public class SVGCanvas extends JSVGCanvas {
private static final long serialVersionUID = 1L;
/**
* The type of scale
*/
private short svgScale;
/**
* Image padding
*/
private int svgPadding;
public SVGCanvas() {
this.svgScale = SVGPreserveAspectRatio.SVG_PRESERVEASPECTRATIO_XMIDYMAX;
this.svgPadding = 5;
}
#Override
protected AffineTransform calculateViewingTransform(String svgElementIdentifier, SVGSVGElement svgElement) {
SVGRect svgElementBounds = svgElement.getBBox();
float[] svgElementBoundsVector = new float[] {
svgElementBounds.getX(),
svgElementBounds.getY(),
svgElementBounds.getWidth(),
svgElementBounds.getHeight()
};
float svgEemenetScaleToHeight = getHeight() - svgPadding;
float svgElementScaleToWidth = getWidth() - svgPadding;
return ViewBox.getPreserveAspectRatioTransform(
svgElementBoundsVector, svgScale, true,
svgElementScaleToWidth,
svgEemenetScaleToHeight
);
}
public void setSvgScale(short svgScale) {
this.svgScale = svgScale;
}
public void setSvgPadding(int svgPadding) {
this.svgPadding = svgPadding;
}
}

Set clipboard to transparent image

I am creating a program that needs to copy an image to clipboard.
The problem is that the image has a transparent background and, whenever I copy it, the image comes out with a black background instead of transparent.
I tried lots of things since 2 days ago but none worked.
The class imageSelection is based on http://www.java2s.com/Tutorial/Java/0120__Development/SettinganimageontheclipboardwithacustomTransferableobjecttoholdtheimage.htm
package Package1;
import java.awt.Image;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
/** Transferable image */
public class imageSelection implements Transferable {
private Image image;
/** Creates a "transferable image" */
public imageSelection(Image image) {
this.image = image;
}
public DataFlavor[] getTransferDataFlavors() {
DataFlavor[] transferData = new DataFlavor[] { DataFlavor.imageFlavor }; // <--- Works but gives me a black background instead of transparent
/* I tried this (based on https://stackoverflow.com/questions/15977001/clipboard-copy-from-outlook-always-has-black-background-set-when-retrieved-as-im) but wasn't able to achieve any good result with it.
DataFlavor transferData = null;
try {
transferData = new DataFlavor(Image.class, null); // <---- How to get an object of the type DataFlavor[] from this ( DataFlavor("image/x-emf") is of the type DataFlavor, not DataFlavor[] )
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
error.displayError(e.getStackTrace(), "Error creating DataFlavor (mime type: image/x-emf)");
}
return new DataFlavor[] { transferData }
*/
return transferData;
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
return DataFlavor.imageFlavor.equals(flavor);
}
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
if (!DataFlavor.imageFlavor.equals(flavor)) {
throw new UnsupportedFlavorException(flavor);
}
return image;
}
}
Call:
imageSelection imgSel = new imageSelection(new ImageIcon(emojiLocation).getImage());
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(imgSel, null);
Thanks
I am testing the contents by pasting it into Discord (chat app and it does support transparency, I made sure of that).
I am using jdk1.8.0_131.
I am using Windows 10 64bits fully updated.
If needed, full source code here: https://github.com/KingOffNothing/EmojiMenu-for-discord/tree/master/src/Package1
What the program does is change the clipboard to a selected image and then a program written in AHK will simulate the key press ctrl+v that pastes the image.
I was not able to exactly fix the transparency issue but was able to do a workaround (change transparent pixels to match the background's color)
private static BufferedImage fixTransparency(BufferedImage image) {
int width = image.getWidth();
int height = image.getHeight();
Color discordChatColor = new Color(54,57,62, 255);
for (int xx = 0; xx < width; xx++) {
for (int yy = 0; yy < height; yy++) {
Color originalColor = new Color(image.getRGB(xx, yy), true);
if (originalColor.getAlpha() == 0) {
image.setRGB(xx, yy, discordChatColor.getRGB());
}
}
}
return image;
}

JavaFX Transparent Cursor using WritableImage

Edit-Answer:
You can check Fabian's answer and also this library (https://github.com/goxr3plus/JFXCustomCursor)
Actual Question
I want to create a cursor which is fading out in JavaFX so for that i am using a WritableImage and i am continuously reading pixels from the original Image and writing them to a new WritableImage.Then i set a custom cursor to the Scene using ImageCursor(writableImage),below is the full code(give it a try).
The problem is that a get black pixels where transparent pixels are expected.
Note that all the below classes have to be in package sample.
Code(Main):
package sample;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;
public class Main extends Application {
FadingCursor fade = new FadingCursor();
#Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setWidth(300);
primaryStage.setHeight(300);
Scene scene = new Scene(new FlowPane());
primaryStage.setScene(scene);
fade.startFade(scene,100);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Code(FadingCursor)(Edited):
package sample;
import java.util.concurrent.CountDownLatch;
import javafx.application.Platform;
import javafx.scene.ImageCursor;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.PixelReader;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.paint.Color;
public class FadingCursor {
private int counter;
private Image cursorImage;
/**
* Change the image of the Cursor
*
* #param image
*/
public void setCursorImage(Image image) {
this.cursorImage = image;
}
/**
* Start fading the Cursor
*
* #param scene
*/
public void startFade(Scene scene, int millisecondsDelay) {
// Create a Thread
new Thread(() -> {
// Keep the original image stored here
Image image = new Image(getClass().getResourceAsStream("fire.png"), 64, 64, true, true);
PixelReader pixelReader = image.getPixelReader();
// Let's go
counter = 10;
for (; counter >= 0; counter--) {
CountDownLatch count = new CountDownLatch(1);
Platform.runLater(() -> {
// Create the fading image
WritableImage writable = new WritableImage(64, 64);
PixelWriter pixelWriter = writable.getPixelWriter();
// Fade out the image
for (int readY = 0; readY < image.getHeight(); readY++) {
for (int readX = 0; readX < image.getWidth(); readX++) {
Color color = pixelReader.getColor(readX, readY);
// Now write a brighter color to the PixelWriter.
// -------------------------Here some way happens
// the problem------------------
color = new Color(color.getRed(), color.getGreen(), color.getBlue(), (counter / 10.00) * color.getOpacity());
pixelWriter.setColor(readX, readY, color);
}
}
System.out.println("With counter:"+counter+" opacity is:" + writable.getPixelReader().getColor(32, 32).getOpacity());
scene.setCursor(new ImageCursor(writable));
count.countDown();
});
try {
// Wait JavaFX Thread to change the cursor
count.await();
// Sleep some time
Thread.sleep(millisecondsDelay);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
The image(needs to be downloaded)(Right Click ->Save Image as...):
You set the opacity of every pixel to a value only depending on the loop variable here:
color = new Color(color.getRed(), color.getGreen(), color.getBlue(), counter / 10.00);
For transparent pixels (opacity = 0) you actually increase the opacity making the values stored in the other channels (in this case 0 / black) visible. You need to make sure transparent pixels remain transparent, which usually is done like this:
color = new Color(color.getRed(), color.getGreen(), color.getBlue(), (counter / 10.00) * color.getOpacity());
Alternatively you could use deriveColor:
color = color.deriveColor(0, 1, 1, counter / 10d);
Edit
For some reason ImageCursor doesn't seem to like a completely transparent image. You can check that this works, if at least one pixel is not completely transparent by adding
pixelWriter.setColor(0, 0, new Color(0, 0, 0, 0.01));
After the for loops writing the image.
To fix this you could simply use Cursor.NONE instead of an ImageCursor with a fully transparent image:
for (; counter >= 1; counter--) {
...
}
Platform.runLater(() -> scene.setCursor(Cursor.NONE));
 
Alternative without the need to recreate the image/cursor
You could simulate the cursor yourself by moving a image Across the root of the Scene. This won't make the image show up beyond the bounds of the Scene, but you can apply animations to the ImageView for fading instead of modifying the opacity of each pixel manually...
public class CursorSimulator {
private final FadeTransition fade;
public CursorSimulator(Image image, Scene scene, ObservableList<Node> rootChildrenWriteable, double hotspotX, double hotspotY) {
ImageView imageView = new ImageView(image);
imageView.setManaged(false);
imageView.setMouseTransparent(true);
fade = new FadeTransition(Duration.seconds(2), imageView);
fade.setFromValue(0);
fade.setToValue(1);
// keep image on top
rootChildrenWriteable.addListener((Observable o) -> {
if (imageView.getParent() != null
&& rootChildrenWriteable.get(rootChildrenWriteable.size() - 1) != imageView) {
// move image to top, after changes are done...
Platform.runLater(() -> imageView.toFront());
}
});
scene.addEventFilter(MouseEvent.MOUSE_ENTERED, evt -> {
rootChildrenWriteable.add(imageView);
});
scene.addEventFilter(MouseEvent.MOUSE_EXITED, evt -> {
rootChildrenWriteable.remove(imageView);
});
scene.addEventFilter(MouseEvent.MOUSE_MOVED, evt -> {
imageView.setLayoutX(evt.getX() - hotspotX);
imageView.setLayoutY(evt.getY() - hotspotY);
});
scene.setCursor(Cursor.NONE);
}
public void fadeOut() {
fade.setRate(-1);
if (fade.getStatus() != Animation.Status.RUNNING) {
fade.playFrom(fade.getTotalDuration());
}
}
public void fadeIn() {
fade.setRate(1);
if (fade.getStatus() != Animation.Status.RUNNING) {
fade.playFromStart();
}
}
}
#Override
public void start(Stage primaryStage) {
Button btn = new Button("Say 'Hello World'");
btn.setOnAction((ActionEvent event) -> {
System.out.println("Hello World!");
});
StackPane root = new StackPane();
root.getChildren().add(btn);
Scene scene = new Scene(root, 500, 500);
Image image = new Image("http://i.stack.imgur.com/OHj1R.png");
CursorSimulator simulator = new CursorSimulator(image, scene, root.getChildren(), 32, 50);
scene.setOnMouseClicked(new EventHandler<MouseEvent>() {
private boolean fadeOut = true;
#Override
public void handle(MouseEvent event) {
if (fadeOut) {
simulator.fadeOut();
} else {
simulator.fadeIn();
}
fadeOut = !fadeOut;
}
});
primaryStage.setScene(scene);
primaryStage.show();
}
The reason of this question was to create a kind of cursor that can be
modified.For example here i wanted to make it had a fade effect.For
future users who want to create custom cursors i have created a
library on github and i will show some code here:
https://github.com/goxr3plus/JFXCustomCursor
Code:
import javafx.application.Platform;
import javafx.beans.Observable;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Pane;
/**
* This class allows you to set as a Cursor in a JavaFX Scene,whatever you want
* ,even a video!. <br>
* <br>
* <b>What you have to do is create a basic layout,for example:</b><br>
* #-->A BorderPane which contains a MediaView,<br>
* #-->A StackPane which contains an animated ImageView,<br>
* #-->A Pane which contains an animated Rectangle or something more complex
* etc..)<br>
*
* <br>
* <br>
* The options are unlimited!
*
* #author GOXR3PLUS
* #param <T>
* #Version 1.0
*/
public class JFXCustomCursor {
private SimpleIntegerProperty hotSpotX = new SimpleIntegerProperty();
private SimpleIntegerProperty hotSpotY = new SimpleIntegerProperty();
private Scene scene;
private Pane sceneRoot;
private Pane content;
private EventHandler<MouseEvent> eventHandler1;
private EventHandler<MouseEvent> eventHandler2;
private EventHandler<MouseEvent> eventHandler3;
/**
* Constructor
*
* #param scene
* The Scene of your Stage
* #param sceneRoot
* The Root of your Stage Scene
* #param content
* The content of the JFXCustomCursor class
* #param hotspotX
* Represents the location of the cursor inside the content on X
* axis
* #param hotspotY
* Represents the location of the cursor inside the content on Y
* axis
*/
public JFXCustomCursor(Scene scene, Pane sceneRoot, Pane content, int hotspotX, int hotspotY) {
// Go
setRoot(scene, sceneRoot, content, hotspotX, hotspotY);
}
/**
* This method changes the content of the JFXCustomCursor
*
* #param scene
* The Scene of your Stage
* #param sceneRoot
* The Root of your Stage Scene
* #param content
* The content of the JFXCustomCursor class
* #param hotspotX
* Represents the location of the cursor inside the content on X
* axis
* #param hotspotY
* Represents the location of the cursor inside the content on Y
* axis
*/
public void setRoot(Scene scene, Pane sceneRoot, Pane content, int hotSpotX, int hotSpotY) {
// Keep them in case of unRegister-reRegister
unRegister(); // has to be called before the below happens
this.scene = scene;
this.sceneRoot = sceneRoot;
this.content = content;
// hot spots
this.hotSpotX.set(hotSpotX);
this.hotSpotX.set(hotSpotY);
// cursor container
content.setManaged(false);
content.setMouseTransparent(true);
// Keep the Content on the top of Scene
ObservableList<Node> observable = sceneRoot.getChildren();
observable.addListener((Observable osb) -> {
if (content.getParent() != null && observable.get(observable.size() - 1) != content) {
// move the cursor on the top
Platform.runLater(content::toFront);
}
});
if (!observable.contains(content))
observable.add(content);
// Add the event handlers
eventHandler1 = evt -> {
if (!sceneRoot.getChildren().contains(content))
observable.add(content);
};
eventHandler2 = evt -> observable.remove(content);
eventHandler3 = evt -> {
content.setLayoutX(evt.getX() - hotSpotX);
content.setLayoutY(evt.getY() - hotSpotY);
};
scene.addEventFilter(MouseEvent.MOUSE_ENTERED, eventHandler1);
scene.addEventFilter(MouseEvent.MOUSE_EXITED, eventHandler2);
scene.addEventFilter(MouseEvent.MOUSE_MOVED, eventHandler3);
}
/**
* Unregisters the CustomCursor from the Scene completely
*/
public void unRegister() {
if (scene != null) {
sceneRoot.getChildren().remove(content);
scene.removeEventFilter(MouseEvent.MOUSE_ENTERED, eventHandler1);
scene.removeEventFilter(MouseEvent.MOUSE_EXITED, eventHandler2);
scene.removeEventFilter(MouseEvent.MOUSE_MOVED, eventHandler3);
}
}
/**
* Re register the CustomCursor to the Scene,<b>this method is
* experimental(use with caution!)</b>
*/
public void reRegister() {
if (scene != null)
setRoot(scene, sceneRoot, content, hotSpotX.get(), hotSpotY.get());
}
public SimpleIntegerProperty hotSpotXProperty() {
return hotSpotX;
}
public SimpleIntegerProperty hotSpotYProperty() {
return hotSpotY;
}
}

Disable text below barcode image in Code39Bean

This code creates BarCode Image along with Text below image .
I need to remove the text from image .
Code39Bean does not have any property to disable this .
public static ByteArrayOutputStream generateBarcodeImg(String inputId)
throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Code39Bean bean = new Code39Bean();
final int dpi = 150;
/**
* Configure the bar-code generator and makes the narrow bar width
* exactly one pixel.
*/
bean.setModuleWidth(UnitConv.in2mm(1.0f / dpi));
bean.setWideFactor(3);
bean.doQuietZone(false);
try {
/** Set up the canvas provider for monochrome PNG output. */
BitmapCanvasProvider canvas = new BitmapCanvasProvider(baos,
BarCodeConstant.CONTENT_TYPE, dpi,
BufferedImage.TYPE_BYTE_BINARY, false, 0);
/** Generate the bar code. */
bean.generateBarcode(canvas, inputId);
/** Signal end of generation. */
canvas.finish();
} catch (IOException e) {
logger.error(
"Exception occured in BarcodeGeneration: generateBarcodeImg "
+ e.getLocalizedMessage(), e);
throw new MobileResourceException(
"Exception occured in BarcodeGeneration: generateBarcodeImg",
null);
}
return baos;
}
}
You can remove the text from Image through the "HumanReadablePlacement" property:
bean.setMsgPosition(HumanReadablePlacement.HRP_NONE);
This will suppress the human readable text of the barcode to NONE.

Image won't paint to animation

Having problems loading/showing an image in a java applet. Not sure if I'm loading the image incorrectly or if I'm accessing it incorrectly. Here's the code that draws the ship and the background(it's an asteroid-like game). The background draws correctly but the ship doesn't. This is the main class method that I'm dealing with:
public void paintFrame(Graphics g) {
Dimension d = size();
g.fillRect(0, 0, d.width, d.height);
g.drawImage(ship.getImage(), d.width/2, d.height/2, null);
}
I create an instance of the ship class at the beginning of the class. However, if I try to instantiate the ship class in a method (such as "Ship ship = new Ship();), it says the variable "ship" is never used.
Here's the entire ship class:
public class Ship {
private int dx;
private int dy;
private int x;
private int y;
private Image image;
public Ship() {
ImageIcon ii = new ImageIcon("ship1.png");
image = ii.getImage();
}
public Image getImage() {
return image;
}
}
If I run it as is, it runs without errors, but it doesn't display the ship. If I try to create the instance of the ship anywhere else except at the top, it gives me a NullPointerException.
Update
Here's my entire main class:
import java.applet.Applet;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
public class RunGame extends Applet implements Runnable {
int frame;
int delay;
Thread animator;
Ship ship = new Ship();
Level level;
Dimension offDimension;
Image offImage;
Graphics offGraphics;
/**
* Initialize the applet and compute the delay between frames.
*/
public void init() {
String str = getParameter("fps");
int fps = (str != null) ? Integer.parseInt(str) : 10;
delay = (fps > 0) ? (1000 / fps) : 100;
}
/**
* Method is called when the applet becomes visible on
* the screen.
*/
public void start() {
animator = new Thread(this);
animator.start();
}
/**
* This method is called by the thread that was created in
* the start method. It does the main animation.
*/
public void run() {
// Remember the starting time
long tm = System.currentTimeMillis();
while (Thread.currentThread() == animator) {
// Display the next frame of animation.
repaint();
// Delay depending on how far we are behind.
try {
tm += delay;
Thread.sleep(Math.max(0, tm - System.currentTimeMillis()));
} catch (InterruptedException e) {
break;
}
// Advance the frame
frame++;
}
}
/**
* This method is called when the applet is no longer
* visible. Set the animator variable to null so that the
* thread will exit before displaying the next frame.
*/
public void stop() {
animator = null;
offImage = null;
offGraphics = null;
}
/**
* Update a frame of animation.
*/
public void update(Graphics g) {
Dimension d = size();
// Create the offscreen graphics context
if ((offGraphics == null) || (d.width != offDimension.width) || (d.height != offDimension.height)) {
offDimension = d;
offImage = createImage(d.width, d.height);
offGraphics = offImage.getGraphics();
}
// Erase the previous image
offGraphics.setColor(getBackground());
offGraphics.fillRect(0, 0, d.width, d.height);
offGraphics.setColor(Color.black);
// Paint the frame into the image
paintFrame(offGraphics);
// Paint the image onto the screen
g.drawImage(offImage, 0, 0, null);
}
/**
* Paint the previous frame (if any).
*/
public void paint(Graphics g) {
if (offImage != null) {
g.drawImage(offImage, 0, 0, null);
}
}
/**
* Paint a frame of animation.
*/
public void paintFrame(Graphics g) {
Dimension d = size();
g.fillRect(0, 0, d.width, d.height);
//g.drawImage(level.getImage(), 0, 0, null);
g.drawImage(ship.getImage(), 400, 300, null);
}
}
ImageIcon ii = new ImageIcon("ship1.png");
The ImageIcon constructor that accepts a String presumes the string represents ..
..a file name or a file path.
'Applets and files do not mix.' Only a trusted applet can load a File object, and even then, only from the file system of the end user. The File objects cannot point back to the server.
Applets would more typically work with paths formed from an URL. The Applet class provides a number of methods to help form that URL, and the ImageIcon constructor is overloaded to accept an URL.
..Not sure if I'm loading the image incorrectly or if I'm accessing it incorrectly.
Debugging 101 is to display the image immediately after loading it. Drop the image icon into a label and use a JOptionPane to show the label.
Without seeing your full code we can't really tell what's going on with the exception, but in your call to drawImage() specify 'this' as the last parameter instead of null. Images are loaded asynchronously and so they need something that implements ImageObserver (such as your frame) to tell when they have managed to load a bit more (or all of it) - so that they can repaint.

Categories