Question

This code is supposed to display a background image and the player. But it just comes up with a pink screen. I can't really figure out where the problem is coming from, here is my code.

package main;

import java.awt.*;
import javax.swing.ImageIcon;    
import javax.swing.JFrame;

public class Images extends JFrame {

    public static void main(String Args[]) {

        DisplayMode dm = new DisplayMode(800, 600, 16, DisplayMode.REFRESH_RATE_UNKNOWN); // This is going to take 4 parameter, first 2 is x and y for resolotion. Bit depth, the number of bits in a cloour
                                                                                            // 16 is your bit depth. the last one is the monitor refresh, it means it will refres how much it wants
        Images i = new Images(); // making an object for this class
        i.run(dm); // making a run method and is taking the dm as a parameter, in this method we are putting stuff on the screen.
    }

    private Screen s; // Creating the Screen, from the Screen.java
    private Image bg; // Background
    private Image pic; // Face icon
    private boolean loaded; // Making the loaded

    //Run method
    private void run(DisplayMode dm) { // this is where we do things for the screen
        setBackground(Color.PINK); // Setting the Background
        setForeground(Color.WHITE); // Setting the ForeGround
        setFont(new Font("Arial", Font.PLAIN, 24)); // setting the font

        s = new Screen(); // now we can call ALL methods from the Screen object
        try {
            s.setFullScreen(dm, this); // This is setting the full screen, it takes in 2 parameters, dm is the display mode, so its setting the display settings, the next part is the this, what is just s, the screen object.
            loadpics(); // calling the loadpics method
            try { // so if that try block works, then it will put it to sleep for 5 seconds
                Thread.sleep(5000); // its doing this because, at the bottom (s.restorescreen) this makes it into a window again. so it needs to show it for 5 seconds.
            } catch (Exception ex) {
            }
        } finally {
            s.restoreScreen();
        }
    }

    // Loads Pictures
    private void loadpics() {
        System.out.println("Loadpics == true");
        bg = new ImageIcon("Users/georgebastow/Picture/background.jpg").getImage(); // Gets the background
        pic = new ImageIcon("Users/georgebastow/Picture/Player.png").getImage(); // Gets the Player
        System.out.println("Loaded == true in da future!");
        loaded = true; // If the pics are loaded then...    
    }

    public void paint(Graphics g) {
        if (g instanceof Graphics2D) { // This has to happen, its saying if g is in the class Graphics2D, so if we have the latest version of java, then this will run 
            Graphics2D g2 = (Graphics2D) g; // Were making the Text smooth but we can only do it on a graphcis2D object.
            g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); // we are making the text aniti alias and turning it on!(it means making the text smooths! :) )
        }
        if(loaded == true){
            System.out.println("Loaded == true3");
            g.drawImage(bg,0,0,null);
            g.drawImage(pic, 170, 180, null);
            System.out.println("Loaded == true4");
        }
    }    
}

Many Thanks in Advance

Was it helpful?

Solution

When using images, you want to load them through URL with Class.getResource(), which returns a URL. Passing a String the the ImageIcon will cause the image to be looked up through the file system. Though this may work during development in your IDE, you'll come to find out it won't work at time of deployment. Better make the changes now. To use this method, you want do this

ImageIcon icon = new ImageIcon(Images.class.getResource("/Users/georgebastow/Picture/background.jpg"));

For this to work though, you file structure needs to look like this

ProjectRoot
          src
             Users
                  georgebastow
                            Picture
                                  background.jpg

A more common approach is just to put the image a reousrces folder in the src

ProjectRoot
          src
             resources
                     background.jpg

And use this path

ImageIcon icon = new ImageIcon(Images.class.getResource("/resources/background.jpg"));                     

When you build, your IDE will transfer the images to the class path.


Side Note

  • Don't paint on top level containers like JFrame. Instead use JPanel or JComponent and override the paintComponent method. if using JPanel, you should also call super.paintComponent in the paintComponent method.
  • Run you Swing Apps from the Event Dispatch Thread like this

    public static void main(String[] args) {
        SwingUtiliities.invokeLater(new Runnable(){
            public void run() {
                new Images();
            }
        });
    }
    

    See Initial Thread

  • Don't call Thread.sleep(). When running from the EDT (like you should), you will block it. Instead use a java.swing.Timer if it's animation you're looking for. Even if it's not animation, still use it! See this example for Timer program.

  • Also as @mKorbel mentioned, you never add anything to the frame.

UPDATE

Run this example. I also forgot to mention, when you paint on JPanel you also want to override the getPreferredSize(). This will give your panel a size.

src/resources/stackoverflow5.png

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class TestImage {

    public TestImage() {
        JFrame frame = new JFrame("Test Image");
        frame.add(new NewImagePanel());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    public class NewImagePanel extends JPanel {

        private BufferedImage img;

        public NewImagePanel() {
            try {
                img = ImageIO.read(TestImage.class.getResource("/resources/stackoverflow5.png"));
            } catch (IOException ex) {
                System.out.println("Could not load image");
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(600, 600);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawImage(img, 0, 0, getWidth(), getHeight(), this);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TestImage();
            }
        });
    }
}

OTHER TIPS

  1. JFrame isn't proper component (its container) for displaying an Image

  2. usage of paint() for JFrame isn't proper way how to display image or custom painting, graphics

  3. use JLabel with setIcon() in the case isn't JFrame used as container and there are/isn't any JComponent(s) in the JFrame

  4. use JPanel (put to the JFrame.CENTER area) with override paintComponent(instead of paint) in the case that there will be JPanel used as container for another JComponent(s)

  5. more in Oracle tutorial Working with Images

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top