2013-12-15 2 views
4

Я просматриваю SO и Google некоторое время для ответа на этот вопрос, но я не могу найти тот, который действительно работает. Я начну с начала:Показывать неопределенный JProgressBar при запуске командного файла

Я создал класс Java с методом, который запускает командный файл в фоновом режиме (окно команд не появляется). Программа отлично работает, за исключением того, что она будет немного запутывать конечного пользователя, так как пакетный файл занимает некоторое время, чтобы завершить - пользователь не будет знать, продолжает ли программа работать или нет. После завершения исполнения командного скрипта появляется диалоговое окно с сообщением о завершении работы, но за период времени между запуском метода и появлением диалогового окна выглядит так, как будто программа ничего не делает.

Итак, вот мой вопрос: мне очень хотелось бы отобразить новый фрейм с текстовой областью, которая отображает вывод командного файла. Однако я понимаю, что это очень трудно обойтись без создания временных файлов, записи на них, чтения из них и т. Д. Я бы предпочел избежать этого, если это возможно. Поэтому я решил, что лучше будет отображать неопределенный JProgressBar во время выполнения процесса и закрыть его, когда процесс будет завершен. К сожалению, я не думаю, что Swing может справиться с этим, поскольку для этого потребуется запустить сразу несколько процессов. Я слышал о SwingWorker, но не совсем уверен, как это будет использоваться в этом случае. У меня есть следующий SSCCE, который работает, но не имеет реализованного шага выполнения.

public myClass(){ 
    public static void main(String[] args){ 
     String[] commands = {"cmd.exe", "/C", "C:\\users\\....\\myBat.bat"}; 
     Process p = Runtime.getRuntime().exec(commands); 
     p.waitFor() 
     JOptionPane.showMessageDialog(null, "Process finished!"); 
    } 
} 

Пока p.waitFor() ждет процесса, на экране ничего нет. Я просто хочу, чтобы пользователь показывал, что процесс все еще запущен. Мысли? Благодаря!

ответ

10

Вы можете запустить в фоне SwingWorker в ProcessBuilder, как показано ниже, чтобы получить как выход и индикатор.

image

import java.awt.BorderLayout; 
import java.awt.EventQueue; 
import java.awt.event.*; 
import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import javax.swing.*; 

/** 
* @se http://stackoverflow.com/a/20603012/230513 
* @see http://stackoverflow.com/a/17763395/230513 
*/ 
public class SwingWorkerExample { 

    private final JLabel statusLabel = new JLabel("Status: ", JLabel.CENTER); 
    private final JTextArea textArea = new JTextArea(20, 20); 
    private JButton startButton = new JButton("Start"); 
    private JButton stopButton = new JButton("Stop"); 
    private JProgressBar bar = new JProgressBar(); 
    private BackgroundTask backgroundTask; 
    private final ActionListener buttonActions = new ActionListener() { 
     @Override 
     public void actionPerformed(ActionEvent ae) { 
      JButton source = (JButton) ae.getSource(); 
      if (source == startButton) { 
       textArea.setText(null); 
       startButton.setEnabled(false); 
       stopButton.setEnabled(true); 
       backgroundTask = new BackgroundTask(); 
       backgroundTask.execute(); 
       bar.setIndeterminate(true); 
      } else if (source == stopButton) { 
       backgroundTask.cancel(true); 
       backgroundTask.done(); 
      } 
     } 
    }; 

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

     JPanel panel = new JPanel(); 
     panel.setBorder(
      BorderFactory.createEmptyBorder(5, 5, 5, 5)); 
     panel.setLayout(new BorderLayout(5, 5)); 

     JScrollPane sp = new JScrollPane(); 
     sp.setBorder(BorderFactory.createTitledBorder("Output: ")); 
     sp.setViewportView(textArea); 

     startButton.addActionListener(buttonActions); 
     stopButton.setEnabled(false); 
     stopButton.addActionListener(buttonActions); 
     JPanel buttonPanel = new JPanel(); 
     buttonPanel.add(startButton); 
     buttonPanel.add(stopButton); 
     buttonPanel.add(bar); 

     panel.add(statusLabel, BorderLayout.PAGE_START); 
     panel.add(sp, BorderLayout.CENTER); 
     panel.add(buttonPanel, BorderLayout.PAGE_END); 

     frame.setContentPane(panel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    private class BackgroundTask extends SwingWorker<Integer, String> { 

     private int status; 

     public BackgroundTask() { 
      statusLabel.setText((this.getState()).toString()); 
     } 

     @Override 
     protected Integer doInBackground() { 
      try { 
       ProcessBuilder pb = new ProcessBuilder("ls", "-lR", "/"); 
       pb.redirectErrorStream(true); 
       Process p = pb.start(); 
       String s; 
       BufferedReader stdout = new BufferedReader(
        new InputStreamReader(p.getInputStream())); 
       while ((s = stdout.readLine()) != null && !isCancelled()) { 
        publish(s); 
       } 
       if (!isCancelled()) { 
        status = p.waitFor(); 
       } 
       p.getInputStream().close(); 
       p.getOutputStream().close(); 
       p.getErrorStream().close(); 
       p.destroy(); 
      } catch (IOException | InterruptedException ex) { 
       ex.printStackTrace(System.err); 
      } 
      return status; 
     } 

     @Override 
     protected void process(java.util.List<String> messages) { 
      statusLabel.setText((this.getState()).toString()); 
      for (String message : messages) { 
       textArea.append(message + "\n"); 
      } 
     } 

     @Override 
     protected void done() { 
      statusLabel.setText((this.getState()).toString() + " " + status); 
      stopButton.setEnabled(false); 
      startButton.setEnabled(true); 
      bar.setIndeterminate(false); 
     } 

    } 

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

Это фантастика! Мне придется немного поработать с ним, чтобы он соответствовал моим потребностям. Это должен быть отдельный класс и передать мои команды процесса в него. В настоящее время у меня есть переменная класса и метод мутатора для установки значения. По какой-то причине, хотя он не запускает командный файл. Я сделаю немного больше отладки и вернусь к вам. – DerStrom8

+0

Он работает как ожидалось, большое спасибо! К сожалению, он работает очень медленно. Я не думаю, что это может быть ускорено? – DerStrom8

+0

Я бы предположил, что это пакетный файл; Я должен был замедлить его, чтобы проверить; [profile] (http://stackoverflow.com/q/2064427/230513). – trashgod

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