2012-01-17 1 views
2

Я хочу показать модальное диалоговое окно, которое заблокирует мое главное окно, и я хочу контролировать его извне методами showLoadingDialog(), hideLoadingDialog() и setLoadingMessage (String message) - я попробовал этот код, но не работает - Загрузка диалоговое окно отображается, но без сообщенияКак показать диалог занятости/работы/загрузки с динамическим сообщением

import java.awt.GridLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.JButton; 
import javax.swing.JDialog; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 

public class LoadingExample { 


private static class LoadingDialog extends JDialog { 

private JLabel label = new JLabel("working"); 

public LoadingDialog(JFrame owner) { 

    super(owner, ModalityType.APPLICATION_MODAL); 

    setUndecorated(true); 
    add(label); 
    pack(); 

    // move window to center of owner 
    int x = owner.getX() 
     + (owner.getWidth() - getPreferredSize().width)/2; 
    int y = owner.getY() 
     + (owner.getHeight() - getPreferredSize().height)/2; 
    setLocation(x, y); 



    repaint(); 


} 

public void setMessage(String message) { 
    label.setText(message); 
} 


} 



private static LoadingDialog loadingDialog; 


public static void main(String[] args) { 


final JFrame mainWindow = new JFrame("Main frame"); 
mainWindow.setLayout(new GridLayout(3, 3)); 


for (int i = 1; i <= 9; i++) { 

    final int workTime = i; 

    JButton workButton = new JButton("work for " + i + " second"); 

    //action listener, which had to show loading dialog and countdown seconds before finish 
    workButton.addActionListener(new ActionListener() { 

    @Override 
    public void actionPerformed(ActionEvent e) { 

     showLoadingDialog(mainWindow); 

     for (int j = 0; j < workTime; j++) 
     try { 

      // ... do some work here 

      setLoadingMessage("remain " + (workTime - j) 
       + " second(s)"); 
      loadingDialog.repaint(); 
      Thread.sleep(1000); 
     } catch (InterruptedException e1) { 
      e1.printStackTrace(); 
     } 

     hideLoadingDialog(); 
    } 
    }); 


    mainWindow.add(workButton); 

} 

mainWindow.pack(); 
mainWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
mainWindow.setLocationRelativeTo(null); 



mainWindow.setVisible(true); 

} 




public static void showLoadingDialog(JFrame owner) { 
if (loadingDialog != null) 
    loadingDialog.dispose(); 



loadingDialog = new LoadingDialog(owner); 

new Thread() { 
    @Override 
    public void run() { 
    loadingDialog.setVisible(true); 
    }; 
}.start(); 

} 

public static void setLoadingMessage(String message) { 
loadingDialog.setMessage(message); 
} 


public static void hideLoadingDialog() { 

if (loadingDialog != null) { 
    loadingDialog.setVisible(false); 
    loadingDialog.dispose(); 
    loadingDialog = null; 
} 


} 

} 

спасибо за любые предложения

+4

"* Я пробовал этот код, но его не работает *" - что не работает? Вы можете использовать «SwingWorker», который выполнит задачу в фоновом режиме, а затем обновит GUI (т. Е. Сообщение и, возможно, индикатор выполнения), чтобы отразить его прогресс. – mre

+2

Прочитайте http://docs.oracle.com/javase/tutorial/uiswing/concurrency/ –

+0

, если я получу это правильно, SwingWorker может помочь мне выполнить задачу в фоновом режиме, но я хочу заблокировать ui во время работы, потому что какая-то другая часть приложения. Или вы предлагаете использовать SwingWorker для показа LoadDialog? то как выглядит эти методы методы showLoadingDialog(), hideLoadingDialog() и setLoadingMessage (String message)? thanks :) – user1154034

ответ

0

Вы не можете вносить изменения в GUI из другого потока, чем поток диспетчера, связанный с элементом управления, который вы пытаетесь изменить. Для того, чтобы сделать это правильно, вы можете использовать SwingUtilities.InvokeLater:

new Thread() { 
    @Override 
    public void run() { 

     SwingUtilities.InvokeLater(new Runnable() { 
      public void run() { 
       loadingDialog.setVisible(true); 
      } 
     }); 

    }; 
}.start(); 
0

Я хотел написать некоторые примеры кода, но перед обжигом мой IDE я сделал небольшой поиск в отличном Swing concurrency tutorial и вот, она содержит именно образец кода вы находясь в поиске. У вас есть 'task that has interim results'. Поэтому, когда у вас есть промежуточные результаты, вы вызываете метод SwingWorker#publish. В методе SwingWorker#process вы обновляете модальный диалог с новым опубликованным сообщением. Метод SwingWorker#done позволяет впоследствии удалить модальный диалог.

Но я предлагаю вам прочитать весь учебник по параллелизму от начала до конца, так как ваш образец кода показывает, что вам не хватает базовых знаний о потоке Swing.