Q:

Why my JLabel don't updating properly in loop?

I want to make a loading screen for my application, but the JLabel which shows how much loaded doesn't updating properly.
I created a JDialog and JLabel. I want to update JLabel text via a Thread.
JDialog loadingScreen = new JDialog((JFrame) null);
JLabel loaded = new JLabel();
loadingScreen.add(loaded);
loading.add(time);
loading.setSize(new Dimension(200,100));

Thread t = new Thread(() -> {
    loading.setVisible(true);
    while (true) {
        if (i3 < Math.pow(characters.size(), Integer.parseInt(length.getText()))) {
            time.setText(i3 + " / " + Math.pow(characters.size(), Integer.parseInt(length.getText()))); //doesn't work
            System.out.println("hi"); //works
        } else break;
    }
});
...
t.start();

A:

Don't update Swing components via a Thread. Instead, use SwingUtilities.invokeLater, like so:
JDialog loadingScreen = new JDialog((JFrame) null);
JLabel loaded = new JLabel();
loadingScreen.add(loaded);
loading.add(time);
loading.setSize(new Dimension(200,100));

Thread t = new Thread(() -> {
    loading.setVisible(true);
    while (i3 < Math.pow(characters.size(), Integer.parseInt(length.getText()))) {
        SwingUtilities.invokeLater(() -> time.setText(i3 + " / " + 
            Math.pow(characters.size(), Integer.parseInt(length.getText()))));
        System.out.println("hi");
    }
});
...
t.start();

Naturally, use proper syntax for the Runnable lambda - if it's multi-line, you must use a block. However, using a Thread to update Swing GUI components is not recommended. Often, Swing Timers are a better idea.

