2013-08-03 2 views
1

Есть ли способ написать текст в JTextArea о фоновом процессе. У меня есть одна кнопка на экране. Когда пользователь нажимает на эту кнопку, запускается какой-то процесс. Я хочу показать текущий статус этого процесса на экране, который находится в области «Текст». После выполнения textArea.append("Some status") я использую, чтобы позвонить textArea.repaint(), но это не работает для меня.Показать статус фона в JTextArea

Должен ли я реализовать собственную тему для этого?

ответ

4

Вы можете использовать SwingWorker, где вам действительно не нужно беспокоиться о выполнении периодической задачи на Event Dispatcher Thread. Вы просто вызовете publish() внутри метода doInBackground(), чтобы добавить указанный текст к JTextArea, который будет вызывать process() и выполнить всю задачу на Event Dispatcher Thread автоматически.

Посмотрите на это рабочий пример:

import java.awt.*; 
import java.awt.event.*; 
import java.net.URL; 
import javax.imageio.ImageIO; 
import javax.swing.*; 

public class LoadingImage { 

    private JPanel contentPane; 
    private JTextArea logArea; 
    private JLabel imageLabel; 
    private ImageIcon[] images; 
    private JButton startStopButton; 
    private String[] path; 
    private int counter; 

    private Timer timer; 

    private ActionListener timerAction = 
          new ActionListener() { 
     @Override 
     public void actionPerformed(ActionEvent ae) { 
      counter %= path.length; 
      imageLabel.setIcon(images[counter++]); 
     } 
    }; 

    private ActionListener buttonAction = 
          new ActionListener() { 
     @Override 
     public void actionPerformed(ActionEvent ae) { 
      if (timer.isRunning()) { 
       startStopButton.setText("Start"); 
       timer.stop(); 
      } 
      else { 
       startStopButton.setText("Stop"); 
       timer.start(); 
      } 
     } 
    }; 

    public LoadingImage() { 
     imageLabel = new JLabel("Nothing to display yet...", JLabel.CENTER); 
     images = new ImageIcon[5]; 
     path = new String[] { 
      "http://i.imgur.com/922oehL.gif", 
      "http://i.imgur.com/2Fim5t4.gif", 
      "http://i.imgur.com/jJKlCiI.gif", 
      "http://i.imgur.com/0KuZuGl.gif", 
      "http://i.imgur.com/evuKoI5.gif" 
     }; 
     counter = 0; 
    } 

    private void displayGUI() { 
     JFrame frame = new JFrame("Loading Image Example"); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 

     contentPane = new JPanel(new BorderLayout(5, 5)); 
     JPanel centerPanel = new JPanel(new GridLayout(1, 2, 5, 5)); 
     logArea = new JTextArea(10, 10); 
     JScrollPane logScroller = new JScrollPane(); 
     logScroller.setViewportView(logArea); 

     centerPanel.add(logScroller); 
     centerPanel.add(imageLabel); 
     contentPane.add(centerPanel, BorderLayout.CENTER); 

     startStopButton = new JButton("Stop"); 
     startStopButton.addActionListener(buttonAction); 
     contentPane.add(startStopButton, BorderLayout.PAGE_END); 

     frame.setContentPane(contentPane); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 

     new BackgroundTask().execute(); 
     timer = new Timer(1000, timerAction); 
     timer.start(); 
    } 

    private class BackgroundTask extends SwingWorker<ImageIcon[], String> { 
     @Override 
     protected ImageIcon[] doInBackground() { 
      ImageIcon[] images = new ImageIcon[path.length]; 
      for (int i = 0; i < path.length; i++) 
      { 
       try { 
       images[i] = new ImageIcon(ImageIO.read(new URL(path[i]))); 
       }catch(Exception e) {e.printStackTrace();} 
       publish(String.format("Loaded : %s%n", path[i])); 
      } 

      return images; 
     } 

     @Override 
     protected void process(java.util.List<String> messages) { 
      for (String message : messages) 
       logArea.append(message); 
     } 

     @Override 
     protected void done() { 
      try { 
       images = get();    
      } catch(Exception e) {e.printStackTrace();} 
     } 
    } 

    public static void main(String[] args) { 
     Runnable runnable = new Runnable() { 
      @Override 
      public void run() { 
       new LoadingImage().displayGUI(); 
      } 
     }; 
     EventQueue.invokeLater(runnable); 
    } 
} 
+0

Это то, что я ищу ...... Спасибо – Navnath

2

Звонок textArea.repaint() совершенно лишний. После вызова append автоматически вызывается repaint, поэтому вам не нужно его вызывать.

Вот пример:

Process p = ...; // start the process somehow 
final BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream())); 
new Thread() { 
    private String line; 
    public void run() { 
     while ((line = br.readLine()) != null) { 
      SwingUtilities.invokeLater(new Runnable() { 
       public void run() { 
        textArea.append(line); 
       } 
      }); 
     } 
    } 
}.start(); 

Этот код должен быть запущен, когда кнопка нажата.

+0

В моем случае, процесс не совсем объект класса Process. Это просто вызов некоторых функций. Не могли бы вы объяснить, как использовать выше спинет? – Navnath

+0

Основополагающими являются: вы начинаете поток, который проверяет ход выполнения функций и периодически вызывает 'JTextArea.append'. – tbodt

+0

'append()' не является потокобезопасным, если вы работаете с Java 7. Так, как указано @bellabax, OP должен использовать SwingWorker (ОДИН, который удалил свой ответ) –

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