Reputation: 930
My code uses Card Layout to display (predefined) JPanels with JButtons to the user, and then show a dynamically generated JPanel with feedback on their response, before proceeding to the next predefined JPanel. However, I can't get the dynamically generated JPanels to display, and having messed around a bit with commands like revalidate() and repaint(), I'm at a loss as to what to try next. I've probably made a fairly simple mistake, but having tried lots of combinations of things, I'm a bit stuck!
Edit: sorry, that was a pretty useless bit of code that I posted earlier! I've taken the time to write a better SSCCE, and it does look like it's to do with using Thread.sleep but I'm not great with that so not too sure what I need to do to make it work properly. Here is my example:
public class ExampleClass implements ActionListener{
public void doStuff(){
ExampleClass ec = new ExampleClass();
startExperiment();
}
public static void main(String[] args){
ExampleClass e = new ExampleClass();
e.doStuff();
}
JPanel j;
int count = 0;
CardLayout cards = new CardLayout();
JButton button;
public void startExperiment(){
// Create frame and JFrames
JFrame trial = new JFrame();
trial.setSize(800,600);
JPanel j1 = new JPanel();
JPanel j2 = new JPanel();
j1.setSize(800,600);
button = new JButton("Click me!");
button.addActionListener(this);
j2.setSize(800,600);
j1.add(new JLabel("A Panel"));
j1.add(button);
j2.add(new JLabel("Another Panel"));
JPanel[] pans = {j1,j2};
j = new JPanel();
j.setLayout(cards);
for(int i=0;i<pans.length;i++){
j.add(pans[i], "Card"+i);
}
JPanel end = new JPanel();
end.add(new JLabel("The end!"));
j.add(end,"End");
trial.add(j);
trial.setVisible(true);
}
public void nextTrial(){
JPanel ps = new JPanel();
ps.add(new JLabel("This panel won't display!"));
j.add(ps,"Pause"+count);
cards.show(j,"Pause"+count);
}
class aThread extends Thread {
public aThread(int duration){
dur=duration;
}
int dur;
public void run() {
try {
Thread.sleep(dur);
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void pause(int dur){
aThread myThread = new aThread(dur);
myThread.start();
try {
myThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void actionPerformed(ActionEvent e) {
if(e.getSource()==button){
System.out.println("Ow!");
nextTrial();
pause(500);
cards.show(j,"Card1");
}
}
}
I realise that this is a similar question to one I asked about 12 months ago here (http://stackoverflow.com/questions/9200072/jpanel-not-updating-cardlayout-properly-when-i-use-sleep?rq=1), but I mistakenly believed that using Thread.join() would solve the problems I mentioned.
Upvotes: 0
Views: 1742
Reputation: 930
Thanks to everyone that answered, for pointing me in the right direction. I figured out in the end, it's to do with my poor understanding of threads and synchronisity. In case anyone else has a similar problem, I solved this by changing the last bit of my code to read:
public void actionPerformed(ActionEvent e) {
if(e.getSource()==button){
nextTrial();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
pause(500);
cards.show(j,"Card1");
}
});
}
}
Upvotes: 0
Reputation: 816
if you have "messed around a bit with commands like revalidate() and repaint(),", then, if this
pause(500);
has anything to do with Thread.sleep(), it is likely to be the problem.
It will block painting, then immediately show the next card.
To be sure, post a sample compilable program, as mentioned earlier.
Upvotes: 1
Reputation: 57381
Add the call
revalidate();
repaint();
after adding/removing components to/from container
Upvotes: 2