0

I'm learning Swing with Java and I've very early on run into an issue with getting my components to show in the window. If I use the following code:

import javax.swing.*;

public class win extends JFrame {

    public static void main(String[] args) {

        new win();
    }

    public win(){

        this.setTitle("WIN");
        this.setSize(200,200);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JLabel l = new JLabel("Label");

        this.add(l);

        this.setVisible(true);
    }
}

my label will not show unless I resize the window. I searched other questions and some suggested that the lack of pack, revalidate, validate and or repaint methods were the culprit. If I add pack to the same code:

import javax.swing.*;

public class win extends JFrame {

    public static void main(String[] args) {

        new win();
    }

    public win(){

        this.setTitle("WIN");
        this.setSize(200,200);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JLabel l = new JLabel("Label");

        this.add(l);

        this.pack();

        this.setVisible(true);
    }
}

My window takes about 10 seconds to display

UPDATE:

Adding my code to the EDT as suggested by Frakcool did not work.

This code also renders after a 10 second delay. I don't think it is a problem with my computer being slow, it is a quad core 32 gb ram machine running High Sierra. Currently I'm running these programs on Java 8.

USING EDT:

Everyone suggest that not using the EDT is the culprit, however I've tried it and it does not seem to be the issue. Unless there is something wrong with this code, the EDT is not the solution:

import javax.swing.*;


public class Window extends JFrame {

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

    }

    public Window(){

        this.setTitle("WINDOW");

        JLabel l = new JLabel("Label");

        this.add(l);

        this.pack();

        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        this.setVisible(true);
    }
}

I'm still getting a 10 second startup just for this one Label, and it is the same with other swing components.

UPDATE:

The issue is definitely not anything in the code (with or without EDT), as I'm able to run this code without delay on both another OSX system (Mojave) and on Ubuntu via Virtualbox on the problem machine (High Sierra). The issue must be with either High Sierra or some settings I have on my personal system or on the JVM

  • 1
    1) You should run your code in the EDT, see point #2 in this [answer](https://stackoverflow.com/questions/42404270/jcomponent-stops-getting-rendered-once-it-goes-off-the-screen/42404808#42404808). – Frakcool Oct 01 '19 at 19:21
  • 1
    2) *"setSize after pack"* Why? You shouldn't be calling `setSize(...)` at all, see [Should I avoid the use of setPreferred|Maximum|MinimumSize?](https://stackoverflow.com/questions/7229226/should-i-avoid-the-use-of-setpreferredmaximumminimumsize-methods-in-java-swi) (Yes, and override your `JComponent`'s `getPreferredSize` method instead, [for example](https://stackoverflow.com/questions/39048263/trouble-with-java-layouts/39048401#39048401). 3) Nothing in your code seems to add those extra 10 seconds, so, maybe your computer is too slow. – Frakcool Oct 01 '19 at 19:22
  • `this.validate` and `this.repaint` won't do much as you're not changing the `JFrame` size dynamically or adding / deleting components during the execution of this program. And btw, please follow [Java Naming Conventions](https://www.oracle.com/technetwork/java/codeconventions-135099.html). `FirstWordUpperCaseClass`, `firstWordLowerCaseVariable`, `firstWordLowerCaseMethod()` and `ALL_WORDS_UPPER_CASE_CONSTANT` and give them meaningful names (not single letter names) as in bigger programs you'll easily get lost if you don't (this also makes it easier for others to understand your code better) – Frakcool Oct 01 '19 at 19:26
  • 1
    “I found this sample code from javatpoint” —Delete that code and never look at it again. There are several things wrong with it. Your original code was better, and probably would have worked if it had been placed in a Runnable which was passed to [EventQueue.invokeLater](https://docs.oracle.com/en/java/javase/13/docs/api/java.desktop/java/awt/EventQueue.html#invokeLater%28java.lang.Runnable%29). – VGR Oct 01 '19 at 21:23
  • I think maybe it is an issue with my version of Java, or perhaps Frakcool is right after all and it was the machine. I ran the same code on my home machine using Java13 and Mojave and it worked fine. I don't think running it in another thread is the issue since it seems to work fine on another machine, thank you for taking the time to help! – PhillVance Oct 01 '19 at 22:05
  • 1
    Tip, to notify someone of your reply, you should add @VGR or whoever you're answering to (The `@` is important). And you never placed your program on the EDT. Also there may be some configurations on the JVM that could be causing this, present on the High Sierra Mac but not on your personal one. However, place your code on the EDT and *DON'T* use `setBounds` and `null` layout! It's [evil](https://www.leepoint.net/GUI/layouts/nulllayout.html) and doesn't work well with `pack`. [Example of its evilness](https://stackoverflow.com/a/42521097/2180785) – Frakcool Oct 02 '19 at 16:25
  • 2
    “Seems to work fine on another machine” is a common symptom of threading problems. You want to write code that works every time on every machine. The way you do that is by making all Swing and AWT code run in the event dispatch thread. – VGR Oct 02 '19 at 16:27
  • @Frakcool thank you for the at Tip. I tried the EDT before and it didn't work, I updated my code above to even show code using it that still has a 10 second start up. Is there something wrong with the code I posted in the update? I hope I'm just making some silly mistake that is easy to fix. Do you have any idea what JVM configuration settings could be causing this? Thanks again for your help – PhillVance Oct 02 '19 at 19:06
  • I'm afraid I'm not confident in the JVM configurations, but I'd reinstall Java from Oracle's site and see if that helps – Frakcool Oct 02 '19 at 19:18

1 Answers1

0

All painting operations in Swing should be executed on the so called Event Dispatch Thread (EDT). Passing a java.lang.Runnable instance - with it's run() method calling these painting operations - to SwingUtilities.invokeLater() method ensures that this code is executed on the EDT. Otherwise issues will arise at some point, for example the so called "grey rect"-issue: The UI of the application seems to lag or even feels like "frozen". See [[https://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html]]

I'd refactor your code to this:

import javax.swing.*;

public class Win extends JFrame {

    Win() {
        super("WIN");
        setSize(200, 200);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    public static void main(String args[]) throws Exception {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new Win();
            JComponent label = new JLabel("Label");
            frame.getContentPane().add(label);
            frame.setVisible(true);
        });
    }
}
  • Updated my original post to show that I'm using the EDT and I still get the start up. Additionally I copy pasted your code and I had the same problem, 10 seconds of nothing, then the window pops up with everything rendered. Someone in the comments suggested that it may be some JVM setting, any ideas? Thank you for your time @Tommy Brettschneider – PhillVance Oct 02 '19 at 19:08