2010-12-10 3 views
5

У меня есть приложение для банковского gui, над которым я сейчас работаю, и, похоже, проблема с setvisible методом для моего jdialog. После того, как пользователь отозвал действительную сумму, я открываю простой диалог, в котором говорится, что «транзакция продолжается». В моем методе dobackground я продолжаю опрос, чтобы проверить, была ли получена транзакция. Я пытался использовать swingworker, и я не понимаю, почему он не работает. Если я удаляю setvisible-вызов, он работает нормально, так почему setvisible заставляет систему зависать? Вот код, который находится внутри моего JButton MouseListener:setvisible метод в java swing зависает система

SwingWorker<String,Integer> worker = new SwingWorker<String,Integer>(){ 

    JDialog waitForTrans = new JDialog((JFrame)null,true); 
    public String doInBackground() throws Exception { 
    waitForTrans.add(new JLabel("Updating balance in system. Please Wait...")); 
    waitForTrans.setMinimumSize(new Dimension(300,100)); 
    waitForTrans.setDefaultCloseOperation(DISPOSE_ON_CLOSE); 
    waitForTrans.setVisible(true); 
    Bank.getInstance().sendTransaction(currentPin,"-"+withdraw); 
    while(!Bank.getInstance().hasCompletedTransaction){ 

    } 
    return null; 

    } 

    public void done(){ 
    try { 
     this.get(); 
     } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } catch (ExecutionException e) { 

     e.printStackTrace(); 
    } 
    waitForTrans.setVisible(false); 
    newField.setText(String.valueOf(Bank.getInstance().getAccountList().get(currentPin).getBalance())); 
    } 

}; 
worker.execute(); 
+0

В какой версии java вы видели эту блокировку? Мы обновили с java 6 до java 8 и могли работать в этом поведении. – simgineer

ответ

13

Во-первых, рекомендуется использовать все обновления графического интерфейса в потоке Swing Event-Dispatch, то есть использовать класс SwingUtilites.

Во-вторых, ваш JDialog является модальным и таким образом блокирует поток, в котором вызывается метод setVisible(true) (в вашем случае Основной поток, в следующем случае Swing Event-Dispatch Thread).

Я не говорю, следующий код является совершенным, но он должен поставить вас на трассе ...

 

final JDialog waitForTrans = new JDialog((JFrame) null, true); 

SwingWorker worker = new SwingWorker() { 

    public String doInBackground() throws Exception { 
    Thread.sleep(5000); 
    return null; 
    } 

    public void done() { 
    SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
     waitForTrans.setVisible(false); 
     waitForTrans.dispose(); 
     } 
    }); 
    } 

}; 

worker.execute(); 
SwingUtilities.invokeLater(new Runnable() { 
    public void run() { 
    waitForTrans.add(new JLabel("Please Wait...")); 
    waitForTrans.setMinimumSize(new Dimension(300, 100)); 
    waitForTrans.setVisible(true); 
    } 
}); 
 

Надеется, что это помогает.

+0

Спасибо за быстрые ответы! Я все еще немного шаткий по этим аспектам для программирования gui, но я получаю это по большей части сейчас ... – Adith

+0

Понимание того, как работает Swing Event-Dispatch Thread и как использовать его правильным образом, было самой сложной частью графического интерфейса Swing для меня. Не торопитесь и получите все правильно, это сэкономит вам массу неприятностей позже. –

+1

Выполненный метод выполняется в Thread Dispatch Thread, поэтому я не думаю, что вам нужно использовать SwingUtilities.invokeLater в этом методе. См. Http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html#done%28%29 – Ryan

5

Вы выводит модальное диалоговое окно, поэтому фон код не может выполняться, пока диалог не будет закрыт.

Добавьте инструкцию System.out.println (...) после setVisible, и вы увидите, что она никогда не выполняется.

+0

Да, я вижу вашу мысль. Спасибо за помощь. – Adith

0

camickr дает правильный ответ. Я хочу добавить, что вы не может изменить пользовательский интерфейс за пределами Событие Dispatch Thread (как вы делаете в #doInBackground), Swing однопоточный, поэтому нарушение этого правила может привести к очень сложным ошибкам и странным вещам в вашем интерфейсе.

1

setVisible - это метод, который влияет на графический интерфейс пользователя, вызывая что-то отображаемое (и в случае модального диалога, подобного вашему, блокируется до тех пор, пока диалог не будет закрыт). Он (как и все остальное, что изменяет видимый интерфейс) должен никогда не вызывать, за исключением потока потока событий Swing. Вы вызываете его из метода doInBackgroundSwingWorker, который работает на фоновом потоке.

Что вам нужно сделать, чтобы исправить это сделать waitForClose диалог final переменных, вы создаете перед вызовом execute на SwingWorker, а затем вызвать setVisible сразу же после того, как начиная работник.

final JDialog waitForTrans = ... 
// set up the dialog here 

SwingWorker<String, Integer> worker = new SwingWorker<String, Integer>() { 
    ... 
}; 
worker.execute(); // start the background process 

waitForTrans.setVisible(true); // show the dialog 

Вам необходимо сделать это в этом порядке, потому что в противном случае модальное диалоговое окно заблокирует вас от запуска рабочего.

Смежные вопросы