The method start in SimpleApplication isn't thread-safe. A simple test with substance look and feel (that includes a thread-safe checking system). The creation of the SettingsDialog should be delegated to the EDT Thread. A possible workaround would be to use an asynchronous approach. I post a (rater ugly) example. The start method becomes:
@Override
public void start(){
// show settings dialog
if (showSettings){
final Object MONITOR = new Object();
final AtomicBoolean release = new AtomicBoolean(false);
final AtomicBoolean accept = new AtomicBoolean(false);
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
URL iconUrl = SimpleApplication.class.getResource("Monkey.png");
SettingsDialog dialog = new SettingsDialog(settings, iconUrl);
final Runnable unlocker = new Runnable() { public void run() {
synchronized(MONITOR) {
release.set(true);
MONITOR.notifyAll();
}
}};
Runnable onAccept = new Runnable() { public void run() {
accept.set(true);
unlocker.run();
}};
Runnable onCancel = new Runnable() { public void run() {
accept.set(false);
unlocker.run();
}};
dialog.showDialog(onAccept, onCancel);
}
});
if(!java.awt.EventQueue.isDispatchThread()) {
synchronized(MONITOR) {
while(!release.get()) {
try {
MONITOR.wait();
} catch(InterruptedException ex) {
ex.printStackTrace();
return;
}
}
if(accept.get()) {
super.start();
}
}
} else {
super.start();
}
} else {
super.start();
}
}[code]
In SettingsDialog one can introduce a couple of fields and a different show method:
[code] private Runnable onAccept, onCancel;
public void showDialog(Runnable onAccept, Runnable onCancel) {
this.onAccept = onAccept;
this.onCancel = onCancel;
showDialog();
}[/code]
And the action listeners for the ok and cancel buttons call the runnables:
[code] ok.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (verifyAndSaveCurrentSelection()){
setUserSelection(APPROVE_SELECTION);
dispose();
if(onAccept != null) {
onAccept.run();
}
}
}
});
cancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setUserSelection(CANCEL_SELECTION);
dispose();
if(onCancel != null) {
onCancel.run();
}
}
});[/code]
It is just a rough sketch of one possible solution.[/code]