Hello all So I'm making progress on my animation program but I'm running into a problem where my alien.png isn't showing up in the jframe. I have the alien.png in the same folder as this animation demo.java so I'm not sure why its not finding the alien.png. Any help would be appreciated
package animationdemo;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class AnimationDemo extends JFrame {
Image alien;
public AnimationDemo() {
alien = Toolkit.getDefaultToolkit().getImage("alien.png");
MovingMessagePanel messagePannel = new MovingMessagePanel();
messagePannel.alien = this.alien;
Timer timer = new Timer(50, messagePannel);
timer.start();
this.add(messagePannel);
}
public static void main(String[] args) {
AnimationDemo frame = new AnimationDemo();
frame.setTitle("Project 10");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
frame.setVisible(true);
}
}
class MovingMessagePanel extends JPanel implements ActionListener {
public int xCoordinate = 20;
public int yCoordinate = 20;
public int xDir=5;
public int yDir=5;
public Image alien;
public void actionPerformed(ActionEvent e) {
repaint();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (xCoordinate > getWidth()) xDir*=-1;
if (yCoordinate > getHeight()) yDir*=-1;
if (xCoordinate <0) xDir*=-1;
if (yCoordinate <0) yDir*=-1;
xCoordinate += xDir;
yCoordinate += yDir;
g.drawImage(alien,xCoordinate,yCoordinate,this);
}
}
Let's look at the code lines:
package animationdemo; // this one!
import java.awt.Graphics;
// ..
public class AnimationDemo extends JFrame {
Image alien;
public AnimationDemo() {
alien = Toolkit.getDefaultToolkit().getImage("alien.png"); // & this one!
That last line is effectively trying to load a File from the 'current directory'.
But the image probably won't be accessible as a File any longer. Application resources will become embedded resources by the time of deployment, so it is wise to start accessing them as if they were, right now. An embedded-resource must be accessed by URL rather than file. See the info. page for embedded resource for how to form the URL.
Note given the first highlit line, the best path for finding the resource would presumably be:
..getResource("/animationdemo/alien.png")
Note also that the getResource method is case sensitive, so ..
..getResource("/animationdemo/alien.PNG")
.. won't find the lower case version, nor vice-versa.
As an aside, I did a check of my 'missing image' theory by making this small change to the source above:
alien = new BufferedImage(40, 40, BufferedImage.TYPE_INT_RGB);
//Toolkit.getDefaultToolkit().getImage("alien.png");
Given I saw an animated black square, it supports the major problem is that the image is not being found. The code still has a few other aspects that should be tweaked, but it is basically going in the right direction.
Related
Recently i decided to start learning how to make 2D games With JAVA ( eclipse ) so i found a tutorial online that shows how to make superMari game with java, i wrote the same code he wrote and i followed step by step what he did, which wasn't a big thing to talk about, unfortunately he's code shows, after excuting, a window with two images in it while mine shows just the window with no images, i ensure you that i imported the two images and put them in one package to avoid all kind of problems but it still shows nothing.
my code has two classes, "main" and "Scene", here it is, hopefully someone will find a solution for me, thank you guys!
Main.java :
package AiMEUR.AMiN.jeu;
import javax.swing.JFrame;
public class Main {
public static Scene scene;
public static void main(String[] args) {
JFrame fenetre = new JFrame("Naruto in mario World!!");
fenetre.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fenetre.setSize(700, 360);
fenetre.setLocationRelativeTo(null);
fenetre.setResizable(false);
fenetre.setAlwaysOnTop(true);
scene = new Scene();
fenetre.setContentPane(scene);
fenetre.setVisible(true);
}
}
Scene.java :
package AiMEUR.AMiN.jeu;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class Scene extends JPanel{
private ImageIcon icoFond;
private Image imgFond1;
private ImageIcon icoMario;
private Image imgMario;
private int xFond1;
public Scene(){
super();
this.xFond1 = -50;
icoFond = new ImageIcon(getClass().getResource("/Images/fond.gif"));
this.imgFond1 = this.icoFond.getImage();
icoMario = new ImageIcon(getClass().getResource("/Images/1.png"));
this.imgMario = this.icoMario.getImage();
// paintComponent(this.getGraphics());
}
public void paintCompenent(Graphics g){
super.paintComponent(g);
Graphics g2 = (Graphics2D)g;
g2.drawImage(this.imgFond1, this.xFond1, 0, null);
g2.drawImage(imgMario, 300, 245, null);
}
}
You have not named the paintComponent method correctly, and therefore it is not being overridden.
The correct name is paintComponent not paintCompenent:
public class Example extends JPanel {
#Override
public void paintComponent(final Graphics g) {
super.paintComponent(g);
}
}
You can determine the loading status of an ImageIcon by doing something like this:
public Scene(){
super();
this.xFond1 = -50;
icoFond = new ImageIcon(getClass().getResource("/Images/fond.gif"));
int status = icoFond.getImageLoadStatus();
switch (status) {
case (MediaTracker.COMPLETE): {
System.out.println("icoFond image has successfully loaded");
}
case (MediaTracker.ERRORED): {
System.out.println("The icoFond image didn't load successfully");
// probably because the image isn't actually at "/Images/fond.gif"
}
}
this.imgFond1 = this.icoFond.getImage();
icoMario = new ImageIcon(getClass().getResource("/Images/1.png"));
this.imgMario = this.icoMario.getImage();
// paintComponent(this.getGraphics());
}
Here is what I'm trying to do - making long story short:
Building a window (will call him MainWindow) with buttons at top and a picture on the center of it. I want to give the user the options to chose what to do (the buttons) while changing the center picture every couple of sec. Part of the options given to the user is 'pause' and 'resume' - controlling the sequence.
Basically trying to update GUI (MainWindow) by a Thread. This Thread will RUN WHILE boolean 'playSequence' will be true.
Can someone explain why can't I get it to work..
Here is the Code:
package SpecializedControls;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import DataEntities.SgiImage;
public class SgiImagePanel extends JPanel implements Runnable {
private List<SgiImage> seqImageList;
private JLabel lastImage;
private boolean playSequence;
public SgiImagePanel (){}
public SgiImagePanel (List<SgiImage> sequenceList)
{
seqImageList = sequenceList ;
}
#Override
public void run() {
// TODO Auto-generated method stub
while(playSequence)
{
for (SgiImage image : seqImageList)
{
display(image);
try {
Thread.sleep(3000);
}
catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public void display(SgiImage image)
{
reset();
JLabel picLabel = new JLabel(new ImageIcon(image.getImage()));
add(picLabel);
lastImage = picLabel;
}
public void display(List<SgiImage> sequenceList)
{
if(sequenceList==null)
return;
playSequence = true;
SgiImagePanel seq = new SgiImagePanel(sequenceList);
Thread thread = new Thread(seq);
thread.start();
}
public void reset(){
if (lastImage != null)
{
remove(lastImage);
lastImage = null;
}
}
public void pause() {
playSequence = false;
}
public void resume(){
playSequence = true;
}
}
Don't directly use Threads for this. There's no need, and it carries risk if you call code in a background thread that changes Swing state without care.
Use a Swing Timer for your animation loop.
Display your images as ImageIcons in a JLabel.
One of the main problems with your code is that you keep creating a bunch of new JLabels needlessly and dangerously. One JLabel is all you need and all you want. So instead, create the image displaying JLabel just once and then swap icons via its setIcon(...) method.
Read in your image Icon just once, and save it in a variable or collection.
You can easily pause a Swing Timer by simply calling its stop() method, and can restart it just as easily by calling start().
Try to load the image with this code:
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
public class ImagePanel extends JPanel{
private BufferedImage image;
public ImagePanel() {
try {
image = ImageIO.read(new File("image name and path"));
} catch (IOException ex) {
// handle exception...
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, null); // see javadoc for more info on the parameters
}
}
I am having somewhat of an issue getting an image from another class. I have never had this problem before. Can someone please point me in the right direction.
package main;
import java.awt.Color;
import java.awt.DisplayMode;
import java.awt.Graphics;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
public class Main extends JFrame {
public static Character character;
static GraphicsEnvironment graphicsEnvironment;
static GraphicsDevice graphicsDevice;
static DisplayMode displayMode;
private Image i;
public static void main(String[] args) {
displayMode = new DisplayMode(1280, 720, 16, DisplayMode.REFRESH_RATE_UNKNOWN);
graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
graphicsDevice = graphicsEnvironment.getDefaultScreenDevice();
Main m = new Main();
m.run();
}
public void run() {
setUndecorated(true);
setResizable(false);
graphicsDevice.setFullScreenWindow(this);
try {
graphicsDevice.setDisplayMode(displayMode);
} catch (Exception e) {
}
}
public void paint(Graphics g) {
g.setColor(Color.cyan);
g.fillRect(0, 0, displayMode.getWidth(), displayMode.getHeight());
i = character.getImage();
g.drawImage(i, 100, 100, this);
}
}
package main;
import java.awt.Image;
import javax.swing.ImageIcon;
public class Character {
private Image i;
public Image getImage() {
i = new ImageIcon(this.getClass().getResource("/raw/images/player1.png")).getImage();
return i;
}
}
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at main.Main.paint(Main.java:52)
It says that the error is i = character.getImage();
I have done this plenty of times when making applets, this if the first time I am trying a fullscreen game
Remember to think about what the compiler is telling you.
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
A NullPointerException means a reference variable hasn't been initialized (or is == null, for that matter). In your case, that means to debug it you'll have to check both i and character. If it was the image you were trying to return, the stacktrace would go one deeper.
Since you are initializing i, look back up at character. You never set character to anything, which means you can't use it in any declarations.
So, your solution is to do character = new Character(); in run() or main(String[] args),
or you can set getImage() to static, and say i = Character.getImage();.
Change the method declaration to
public static Image getImage(){/*your code here */}
And the statement to call that method make sure that the first letter is C in uppercase not c. as in Character.getImage()
So I'm making a game where you can put bombs on the location of your character. Each bomb is associated with a GIF image when the bomb is displayed and eventually go BOOM (think about Bomberman).
The problem was, when i tried to paint more than one bomb on the screen, it was painted from the last frame of the GIF. Investigating, I found the method image.flush() to reset the GIF cicle but now the problem is that every time I paint a second bomb on the screen, the GIF cycle is reset for all previously bombs on screen.
Here is my constructor for each bomb:
public Tnt(int x, int y){
this.x = x;
this.y = y;
ImageIcon ii = new ImageIcon("src/main/resources/modelObjects/tnt.gif");
image = ii.getImage();
image.flush();
}
Every bomb i create enters an ArrayList (listTnt) and is removed after 6 secs, so i only paint the bombs already active.
Here is my method for drawing:
public void draw(Graphics2D g2d, JPanel board){
for(Tnt tnt: listTnt){
g2d.drawImage(tnt.getImage(), tnt.getX(), tnt.getY(), board);
}
}
EDIT: Seems that the problem was ImageIcon, since it reuses the image using Toolkit.getImage. Instead, Toolkit.createImage create a not reusable image.
Here is my new constructor for Tnt that worked perfectly:
public Tnt(int x, int y){
this.x = x;
this.y = y;
Toolkit t = Toolkit.getDefaultToolkit ();
image = t.createImage("src/main/resources/modelObjects/tnt.gif");
}
I dont even need image.flush() now. Thank you all.
The underlying Image is being reused amongst each ImageIcon.
Judging by the OpenJDK source code, it appears to be due to the fact that each simply requests the Image via Toolkit.getImage.
This method has a nifty caveat, however, which explains the issue at hand:
The underlying toolkit attempts to resolve multiple requests with the same filename to the same returned Image.
Instead, you should skip the ImageIcon step completely (since it's inappropriate to be using a Swing class unnecessarily in the first place), and instead call Toolkit.createImage, which states in the documentation:
The returned Image is a new object which will not be shared with any other caller of this method or its getImage variant.
Good luck.
As I did not know how to solve this, I tried #super_ solution and it works quite nicely. I share the code for anyone who wants an example. +1 to him
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class TestAnimatedGif {
private static final int IMAGE_COUNT = 9;
protected void initUI() {
JFrame frame = new JFrame(TestAnimatedGif.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JPanel panel = new JPanel();
frame.add(panel);
frame.setSize(600, 400);
frame.setVisible(true);
final Timer t = new Timer(1000, null);
t.addActionListener(new ActionListener() {
int count = 0;
#Override
public void actionPerformed(ActionEvent e) {
if (count < IMAGE_COUNT) {
try {
JLabel image = new JLabel(new ImageIcon(Toolkit.getDefaultToolkit().createImage(
new URL("http://www.sitevip.net/gifs/bomba/BOMB-B_animado.gif"))));
panel.add(image);
count++;
panel.revalidate();
panel.repaint();
System.err.println("image added");
} catch (MalformedURLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
} else {
t.stop();
}
}
});
t.start();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestAnimatedGif().initUI();
}
});
}
}
Please have a look at the following code
import com.sun.jna.Native;
import uk.co.caprica.vlcj.binding.LibVlc;
import uk.co.caprica.vlcj.component.EmbeddedMediaPlayerComponent;
import uk.co.caprica.vlcj.runtime.RuntimeUtil;
import com.sun.jna.NativeLibrary;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.media.bean.playerbean.MediaPlayer;
import uk.co.caprica.vlcj.player.MediaPlayerEventAdapter;
import uk.co.caprica.vlcj.player.MediaPlayerEventListener;
public class PlayMedia extends JFrame
{
private EmbeddedMediaPlayerComponent m;
private JProgressBar bar;
public PlayMedia()
{
NativeLibrary.addSearchPath(
RuntimeUtil.getLibVlcLibraryName(), "c:\\program files\\videolan\\vlc"
);
Native.loadLibrary(RuntimeUtil.getLibVlcLibraryName(), LibVlc.class);
m = new EmbeddedMediaPlayerComponent();
m.getMediaPlayer().addMediaPlayerEventListener(new UpdateBar());
bar = new JProgressBar(0,100);
bar.setStringPainted(true);
getContentPane().add(m);
getContentPane().add(bar,"South");
this.setSize(500,500);
this.validate();
this.setLocationRelativeTo(null);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
m.getMediaPlayer().playMedia("C:\\Users\\Yohan\\Desktop\\video.avi");
}
private class UpdateBar extends MediaPlayerEventAdapter
{
public void positionChanged(MediaPlayer mp, float pos)
{
int value = Math.min(100, Math.round(pos * 100.0f));
bar.setValue(value);
}
}
public static void main(String[]args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new PlayMedia();
}
});
}
}
In here, video is playing fine, but the progress bar is not getting updated. How to update the progress bar as the video plays? Please help!
I haven't used ProgressBars in Swing, but I have used them in Silverlight, so I would think most of the principles would be the same. Check out the answer to my question here:
How do I make a Silverlight Progressbar update according to its value? It may not show you exactly how to do this in Swing, but it doesn't seem like you're using threading in your code, which is what my problem was.
for some unknown reason positionChanged() isn't called during the video.
try to use timeChanged() istead, it worked for me!
public void positionChanged (MediaPlayer mediaPlayer , long time) { ... }