public class Start extends JFrame{
public static void main(String...s){
Start obj = new Start();
obj.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
obj.setBounds(100,100,300,300);
JPanel main = new JPanel();
obj.add(main);
JButton btn = new JButton("Login");
main.add(btn);
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
obj.setVisible(false);
obj.dispose();
new Progress();
}
});
obj.setVisible(true);
}
}
class Progress extends JFrame{
int pro = 0;
Progress(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setBounds(100,100,300,300);
JPanel main = new JPanel();
add(main);
main.add(new JLabel("ejfbasj"));
JProgressBar progressBar = new JProgressBar(0,100);
main.add(progressBar);
Thread t1 = new Thread() {
public void run() {
while(pro<=100) {
/*
* Do something - set progressbar value
* */
try {
sleep(10);
} catch (InterruptedException e) {}
progressBar.setValue(pro);
pro++;
}
}
};
t1.start();
//Do something - gives progress values
try {
t1.join();
} catch (InterruptedException e) {}
}
}
Above is Minimal, Reproducible Example of my problem.
When Progress JFrame is called from ActionListner, the JFrame doesn't appear properly. I get a black JFrame and after a sec I get final JFrame with full progressbar. But if I call new Progress()
directly, it works properly(i.e. seeing progressbar filling up).
I found that creating new Thread in UI thread is unable to draw Frame. And I should use Swing.Timer
.
I don't know how to do it with Swing.Timer
.
Any other approach is appreciated.
Problem #1
Call
setVisible
last, after you've established the UI. If you need to update the UI after it's visible, you should callinvalidate
andrepaint
to trigger a new layout and paint passProblem #2
Ok, this is actually tw problems.
First, Swing is NOT thread safe and you should not update the UI from outside the context of the Event Dispatching Thread. You should, as you said, either use a Swing
Timer
or probably more suitably, aSwingWorker
Secondly,
t1.join
is blocking the current thread. Because this constructor was called from theActionListener
, this means you're in the context of the Event Dispatching Thread ie, the thread used to update the UI with, so, nothing will change until the thread is completedFor example:
Other problems...
I'd also discuss things about using multiple frames,
setBounds
of things likepack
,setLocationRelativeTo
and using other things like borders or layout constraints to increase the padding, but there are plenty of other examples