0

I need help to add an image to the separate JFrame, but I can't seem to get it to work. Like I want the image to open in a separate frame like when I run this code it opens a blank JFrame. d help to add an image to the separate JFrame, but I can't seem to get it to work. Like I want the image to open in a separate frame like when I run this code it opens a blank JFrame.

import java.awt.event.*; 
import javax.swing.*; 
import java.awt.*;
import javax.swing.JFrame;
class PPJJ extends JFrame implements ActionListener, KeyListener 
{   

public void paint(Graphics g) {  
  
        Toolkit t=Toolkit.getDefaultToolkit();  
        Image i=t.getImage("tenor.gif");  
        g.drawImage(i, 120,100,this);  
          
    }  
    public static void main(String[] args) 
    {
        
        JFrame frame = new JFrame("VOLUNTEER FOR THING"); 
        
        PPJJ obj = new PPJJ(); 
        
        JPanel panel = new JPanel(); 
        
        JLabel lname = new JLabel("Enter your name here");
        JTextField tname = new JTextField(21);
        JButton btn = new JButton("Click"); 
        
        btn.addActionListener(obj); 
        
        tname.addKeyListener(obj); 
        
        panel.add(lname);
        panel.add(tname);
        panel.add(btn); 
        frame.add(panel); 
        frame.setSize(300, 130); 
        frame.show(); 
        frame.setLocationRelativeTo(null);
        
         PPJJ m = new PPJJ();  
        JFrame f =new JFrame();  
        //f.add(m);  
        f.setSize(500,500);  
        f.setVisible(true);  
        frame.add(new JLabel(new ImageIcon("volunteer.jpeg")));

    } 
  
    public void actionPerformed(ActionEvent e) 
    {
        String s = e.getActionCommand(); 
        if(s.equals("Click here")){
            JOptionPane.showMessageDialog(null , "THANKS FOR SIGNING UP");
        } 
    } 
  public void keyPressed(KeyEvent e) {
    if (e.getKeyCode()==KeyEvent.VK_ENTER){
      JOptionPane.showMessageDialog(null , "THANKS FOR SIGNING UP");
    }
  }
    @Override
    public void keyReleased(KeyEvent arg) {}
    @Override
    public void keyTyped(KeyEvent arg) {}
}
CarNage
  • 1
  • 1
  • 2
    I suggest reading about [working directories](https://en.wikipedia.org/wiki/Working_directory) and relative file names versus absolute file names. You are probably running your program in a different working directory than what you think. If your image files are in the same directory as your .class files, use `new ImageIcon(PPJJ.class.getResource("tenor.gif"))`. – VGR May 18 '22 at 02:50
  • 1
    1) Use ImageIO to get the image, 2) get it as a resource *not* as a file. 3) Never, I repeat, ***NEVER***, try to read a file or resource from within a painting method, not unless you want to cripple the perceived responsiveness of your program and re-read images repeatedly and needlessly. Read the image in *once* in code that you control, such as a constructor. 4) Read [The Use of Multiple JFrames, Good/Bad Practice?](http://stackoverflow.com/questions/9554636) – Hovercraft Full Of Eels May 18 '22 at 02:52
  • Now im getting this error Exception in thread "main" java.lang.NullPointerException at javax.swing.ImageIcon.(ImageIcon.java:217) at PPJJ.main(PPJJ.java:45) @VGR – CarNage May 18 '22 at 03:01
  • Do you want the image as the background? Bad idea to try and do this directly on a `JFrame` (ie overriding `paint`) – MadProgrammer May 18 '22 at 03:01
  • yes thats actually better MadProgrammer – CarNage May 18 '22 at 03:02
  • Where is tenor.gif located? Where are your .class files located? Your code seemed to imply they were in the same place, but apparently they are not. – VGR May 18 '22 at 03:05
  • they are both on desktop – CarNage May 18 '22 at 03:08
  • `Toolkit#getImage` will load an image from a file on the disk. Unless specified otherwise, the API will use a relative path from the current working directory, since this change change at runtime, this is not recommended for resources use the app. Instead, embed the image within the app context (how you do this depends on the IDE and build system) and then use `Class#getResource` and `ImageIO` to load the image. For "background" images see [How to set a background picture in JPanel](https://stackoverflow.com/questions/22162398/how-to-set-a-background-picture-in-jpanel/22162430#22162430) – MadProgrammer May 18 '22 at 03:23
  • If you want to show an "icon" of some kind, just use a `JLabel` – MadProgrammer May 18 '22 at 03:23
  • Ok so i got the gif to show up on a separate window just having trouble for it to come up as the background @MadProgrammer – CarNage May 18 '22 at 03:27

1 Answers1

0

Oh, animated GIFs .

Image handling isn't simple in most cases, but animated GIFs are whole other level of pain ... I mean fun.

Normally, I prefer to use ImageIO.read, but ImageIO returns a BufferedImage and it's not (easily) possible to then render animated GIFs through it.

The "easy" route of displaying animated GIFs is by using Image or ImageIcon.

The first step is get your image "embedded" within your application context (assuming that you're not allowing the user to select the image). How this is done will depend on your IDE and build system (Eclipse and Netbeans allow you to simply include them in the src folder, when you're not using Maven).

Next, you want to use Class#getResource to obtain a URL reference to the embedded resource. In this case, you can use ImageIO.read, ImageIcon(URL) or Toolkit#getImage(URL) to load the image. But, as I've said, ImageIO.read isn't going to help you.

Next, you need a component which can render the image, lucky for us, Swing can do this pretty much auto magically for use, all we need to do is make sure the component is passed as the ImageObserver reference, for example...

public class BackgroundPane extends JPanel {
    private Image image;

    public BackgroundPane(Image image) {
        this.image = image;
    }

    @Override
    public Dimension getPreferredSize() {
        Image image = getBackgroundImage();
        return image == null ? super.getPreferredSize() : new Dimension(image.getWidth(this), image.getHeight(this));
    }

    public Image getBackgroundImage() {
        return image;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Image image = getBackgroundImage();
        if (image == null) {
            return;
        }
        int x = (getWidth() - image.getWidth(this)) / 2;
        int y = (getHeight() - image.getHeight(this)) / 2;
        g.drawImage(image, x, y, this);
    }
    
}

Also, note, JLabel supports animated GIFs via it's icon property as well, but look at How to set a background picture in JPanel for reasons why you shouldn't use a JLabel as a background container.

Now, all we need to do is load the image, pass it to the background, add what ever content we need to the component and show it, easy, or at least it should be. ImageIcon and Toolkit#getImage both off load the reading of the image to a background thread, so inspecting the images dimensions before the image is loaded will return 0x0 , so, we need to wait for it to load (this is why I prefer ImageIO.read as it won't return until the image is loaded or an error occurs).

Something like...

Image image = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/images/kitty.gif"));
BackgroundPane backgroundPane = new BackgroundPane(image);
// Did I mention I had this workflow, but ImageIO doesn't
// support animated images, without a lot of work
MediaTracker mt = new MediaTracker(backgroundPane);
mt.addImage(image, 0);
mt.waitForAll();
// The image is now loaded, hooray for us

Runnable example...

enter image description here

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Toolkit;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Main {
    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    Image image = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/images/kitty.gif"));
                    BackgroundPane backgroundPane = new BackgroundPane(image);
                    // Did I mention I had this workflow, but ImageIO doesn't
                    // support animated images, without a lot of work
                    MediaTracker mt = new MediaTracker(backgroundPane);
                    mt.addImage(image, 0);
                    mt.waitForAll();

                    backgroundPane.setLayout(new GridBagLayout());
                    JLabel label = new JLabel("All your kitty is belong to us");
                    label.setForeground(Color.WHITE);
                    backgroundPane.add(label);

                    JFrame frame = new JFrame();
                    frame.add(backgroundPane);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (InterruptedException ex) {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }

    public class BackgroundPane extends JPanel {
        private Image image;

        public BackgroundPane(Image image) {
            this.image = image;
        }

        @Override
        public Dimension getPreferredSize() {
            Image image = getBackgroundImage();
            return image == null ? super.getPreferredSize() : new Dimension(image.getWidth(this), image.getHeight(this));
        }

        public Image getBackgroundImage() {
            return image;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Image image = getBackgroundImage();
            if (image == null) {
                return;
            }
            int x = (getWidth() - image.getWidth(this)) / 2;
            int y = (getHeight() - image.getHeight(this)) / 2;
            g.drawImage(image, x, y, this);
        }

    }
}

Please note...

If you're not using an animated GIF, then you can just use ImageIO.read instead of Toolkit#getImage and you won't need to wait (as ImageIO.read works in the current thread), in which case the code would look more like...

try {
    BackgroundPane backgroundPane = new BackgroundPane(ImageIO.read(getClass().getResource("/images/kitty.gif")));
    backgroundPane.setLayout(new GridBagLayout());
    JLabel label = new JLabel("All your kitty is belong to us");
    label.setForeground(Color.WHITE);
    backgroundPane.add(label);

    JFrame frame = new JFrame();
    frame.add(backgroundPane);
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
} catch (IOException ex) {
    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}

(the BackgroundPane code doesn't change)

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366