-2

I turns out Java has UI, and some even claim people use it. Here's my little app to play around with it a bit (I shortened it a little)

public class App {
    public static void main(String[] args) {
        MyUI ui = new MyUI();
        ui.display();
    }
}
public class MyUI {
    public void display() {
        new UIBuilder()
                .withPanel(() -> new JPanel() {
                    @Override
                    protected void paintComponent(Graphics g) {
                        Image image = new ImageIcon("statics/img.png").getImage();
                        g.drawImage(image, 3, 4, this);
                    }
                })
                .visualize();
    }

    private static class UIBuilder {
        private final JFrame frame;

        { // initialization and defaults
            frame = new JFrame();
            frame.setSize(300, 300);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        }

        private UIBuilder withPanel(Supplier<JPanel> panelSupplier) {
            JPanel panel = panelSupplier.get();
            frame.getContentPane().add(panel);
            return this;
        }

        private UIBuilder withFrameSize(int width, int height) {
            frame.setSize(width, height);
            return this;
        }

        private UIBuilder withDefaultCloseOperation(int windowConstant) {
            frame.setDefaultCloseOperation(windowConstant);
            return this;
        }

        private void visualize() {
            frame.setVisible(true);
        }
    }
}

The problem: no image is displayed. It's a 1200x800 PNG-file. In my attempt to troubleshoot, I changed the panel code to this

        Image image = null;
        try {
            image = ImageIO.read(new File("statics/img.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (image != null) {
            g.drawImage(image, 3, 4, this); // I also tried g.drawImage(image, 3, 4, 200, 150, this);
        } else {
            System.out.println("Error loading image.");
        }

Result:

javax.imageio.IIOException: Can't read input file!
    at java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1310)
    at org.example.demos.ui.MyUI$1.paintComponent(MyUI.java:32)

What is causing the issue? The directory and the file name are ok

enter image description here

UPD: For some reason, specifying the path from the content root helped. If it's in the statics folder, src/main/java/org/example/demos/ui/statics/img.png does the job

new ImageIcon("src/main/java/org/example/demos/ui/statics/img.png").getImage()

I expected relative paths to be resolved relative to the main class directory. It was typically the case before, in other projects. I don't know why it's different here

JoreJoh
  • 113
  • 5
  • 2
    1. Get your image as a resource by using `ImageIO.read(resource)` to get your image. Don't try to get it as a file. 2. Don't keep re-reading the image inside of the paintComponent. This slows down your program's perceived responsiveness and for no gain. Read the image in once, and then *use* it in paintComponent. – Hovercraft Full Of Eels Aug 03 '23 at 21:42
  • @HovercraftFullOfEels I don't understand what you mean by "get your image as a resource". Can you explain it please? – JoreJoh Aug 03 '23 at 21:54
  • @HovercraftFullOfEels If you meant `ImageIO.read(getClass().getResource("statics/img.png"))`, it doesn't help – JoreJoh Aug 03 '23 at 22:01
  • Also, why was it closed? It doesn't seem any of the answers there answer my question – JoreJoh Aug 03 '23 at 22:02
  • 2
    1. This is a common issue, with a common solution; 2. `statics/img.png` is considered and "embedded resource", however, Intillj may require the resource to be added to the "resources" folder and not the "source" folder. In this case I might also consider using an absolute path, just to be sure `org/example/demo/ui/statics/img.png` – MadProgrammer Aug 03 '23 at 22:14
  • Please look at [mad programmer's answer in the duplicate](https://stackoverflow.com/a/20319007/522444) as it tells you what you're doing wrong. You're ignoring where Java is looking for files, you're using files when you shouldn't be. And the duplicate shows you *how* to do it right. – Hovercraft Full Of Eels Aug 03 '23 at 22:15
  • `frame.setSize(300, 300);` - don't use `setSize`, prefer `pack` instead. `JLabel` is usually the most common way to display an image, doesn't mean it's the only way, but if you're not doing anything special with the image, why wouldn't you – MadProgrammer Aug 03 '23 at 22:16
  • @MadProgrammer As a matter of fact, I did try `ImageIO.read(getClass().getResource("org/example/demos/ui/statics/img.png"))`. No luck – JoreJoh Aug 03 '23 at 22:26
  • Yes, but did you move the image to the projects "resource" folder? I can't be 100% sure, but it looks like you're using a Maven based project and it doesn't like "resources" been stored in the "sources" (https://stackoverflow.com/questions/18717038/adding-resources-in-intellij-for-maven-project), but Intillj is also a beast onto itself, which has it's own requirements – MadProgrammer Aug 03 '23 at 22:29
  • @HovercraftFullOfEels he suggested a solution that in my case would look like this, `Image image = new ImageIcon("org/example/demos/ui/statics/img.png").getImage();` No, it doesn't help – JoreJoh Aug 03 '23 at 22:30
  • @MadProgrammer moving it into the `resources` root doesn't help either – JoreJoh Aug 03 '23 at 22:37
  • Wait a sec. If I move it into the resources root *and* change the line to `new ImageIcon("src/main/resources/img.png").getImage()`, the image does appear... Weird. Why should I specify the whole path if it's in the resources root? The whole point of moving something into the resource root is to avoid typing all those directories (from my naive point of view) – JoreJoh Aug 03 '23 at 22:43
  • Update: it doesn't matter whether it's in the resources root. What matters is specifying the path from the content root. If it's in the `statics` folder, `src/main/java/org/example/demos/ui/statics/img.png` works too. Why don't relative paths work? – JoreJoh Aug 03 '23 at 22:55
  • Don't use `src/main/java/` <- this path won't exist once the app is built and exported. I don't use intillj, might be worth taking some time researching it. *"moving it into the resources root doesn't help either"* - move it to `src/main/resources/org/example/demos/ui/statics` then use the `org/example/demos/ui/statics/` path for loading the resource – MadProgrammer Aug 03 '23 at 23:38

0 Answers0