Damien Ramat Damien Ramat - 6 months ago 15
Java Question

Image in JFrame doesn't want to display with the call in another class

I work on a Java development software with Swing and I have a problem with my code, I want to display an image with the LoadingFrame class, its main work but when I call the constructor and the start() method in my main class, the frame opens but the image doesn't display (I have no Exception).
Why it doesn't work with my main class?

public class LoadingFrame
{
private JFrame frame;

public LoadingFrame()
{
frame = new JFrame();
frame.setSize(800, 600);
frame.setLocationRelativeTo(null);
frame.setUndecorated(true);

frame.setContentPane(new Panneau());
}
public void start()
{
frame.setVisible(true);
}

public void stop()
{
frame.setVisible(false);
}

public static void main(String[] args)
{
LoadingFrame l = new LoadingFrame();
l.start();
try
{
Thread.sleep(3000);
}
catch(Exception e)
{
e.printStackTrace();
}

l.stop();
}
}

public class Panneau extends JPanel
{
public void paintComponent(Graphics g)
{
System.out.println("hello");

try
{
Image img = ImageIO.read(new File("Images/loading.png"));
//g.drawImage(img, 0, 0, this);
//Pour une image de fond
g.drawImage(img, 0, 0, this.getWidth(), this.getHeight(), this);
}
catch (IOException e)
{
e.printStackTrace();
}
}
}


The App class is my main class :

public class App {
//Attributes used to display the application
private JFrame frame;

//Attribute which display a waiting frame
private static LoadingFrame loadingFrame;

/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
loadingFrame = new LoadingFrame();
loadingFrame.start();

App window = new App();

loadingFrame.stop();

window.frame.setVisible(true);
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
}

/**
* Create the application.
*/
public App()
{
initialize();
synchronizeScriptReferenceList();
synchronizeTests();
}
[...]
}

Answer

I was able to get this to work from App.java. For some reason, using EventQueue isn't cutting it. I tried to use SwingUtilities as well, but that doesn't work either. Finally I tried just get rid of the Thready-stuff in App.main at just straight up running it in the main thread. For some reason, this works when the other approaches do not! Here is my code:

// In the App class: 

public static void main(String[] args) {
    try {
        loadingFrame = new LoadingFrame();
        loadingFrame.start();

        App window = new App();

        loadingFrame.stop();

        window.frame.setVisible(true);
    } 
    catch (Exception e) 
    {
        e.printStackTrace();
    }
}

When I used this code, I got it to work! (for some reason unknown to me), And here's a bonus rewrite of the Panneau class:

class Panneau extends JPanel
{
    Image img;

    public Panneau() {
        try
        {
            img = ImageIO.read(new File("Images/loading.png"));
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

    @Override
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);

        g.drawImage(img, 0, 0, getWidth(), getHeight(), this);
    }
}

There are two main difference with this class; problems which I addressed. Here they are:

  1. I call super.paintComponent as the very first method in our own paintComponent
  2. I only load the loading image once, in the constructor, and not every single time I want to draw, which moves everything along much smoother. (you don't want the loading screen to be CPU heavy, do you?)

Hopefully, with these improvements, I hope you can make your program work! It worked with me, so I wish the best of luck to you.

P.S. Don't call frame.pack(), that was a mistake on my part. For some reason, I think it doesn't work well with undecorated windows.

Comments