Swingでプロセス実行
昨日のプログラムの応用で、外部コマンドの出力を、SwingのJTextAreaに出力するようにしました。
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;
import javax.swing.text.JTextComponent;
import org.apache.tools.ant.taskdefs.StreamPumper;
/** 外部プロセスを実行し、その標準出力をJTextAreaに表示する. */
public class ProcessOnSwing {
JFrame frame;
JTextField text;
JTextArea area;
JButton button;
OutputStreamTextComponent streamArea;
ProcessOnSwing() {
text = new JTextField("コマンド文字列を入力してね");
text.selectAll();
area = new JTextArea();
area.setEditable(false);
button = new JButton("実行");
button.addActionListener(new ButtonListener());
frame = new JFrame("Swingでプロセス実行");
streamArea = new OutputStreamTextComponent(area);
frame.getContentPane().setLayout(new BorderLayout(5, 5));
JPanel north = new JPanel(new BorderLayout(5, 5));
north.add(text, BorderLayout.CENTER);
north.add(button, BorderLayout.EAST);
frame.getContentPane().add(north, BorderLayout.NORTH);
frame.getContentPane().add(new JScrollPane(area), BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(640, 480);
frame.setVisible(true);
}
/**
* 指定されたプロセスを実行する.
* プロセスは入力を伴わないものとする。
* 標準出力、標準エラー出力を引数のoutに出力される。
* @param command コマンド文字列(ex."java.exe -X")
* @return 戻り値。プロセスの実行に失敗した場合は、Integer.MAX_VALUE
を返す。
*/
int execute(String command, OutputStream out) throws IOException {
Process process = Runtime.getRuntime().exec(command);
Thread outThread;
Thread errThread;
outThread = new Thread(new StreamPumper(process.getInputStream(), out, false));
outThread.setDaemon(true);
errThread = new Thread(new StreamPumper(process.getErrorStream(), out, false));
errThread.setDaemon(true);
outThread.start();
errThread.start();
try {
int exitValue = Integer.MAX_VALUE;
try {
process.waitFor();
} catch (InterruptedException e) {
process.destroy();
}
exitValue = process.exitValue();
try { outThread.join(); } catch (InterruptedException e) {}
try { errThread.join(); } catch (InterruptedException e) {}
out.flush();
try { process.getInputStream().close(); } catch (IOException e) {}
try { process.getOutputStream().close(); } catch (IOException e) {}
try { process.getErrorStream().close(); } catch (IOException e) {}
return exitValue;
} catch (ThreadDeath t) {
process.destroy();
throw t;
}
}
class OutputStreamTextComponent extends OutputStream {
ByteArrayOutputStream out = new ByteArrayOutputStream();
JTextComponent textComponent;
OutputStreamTextComponent(JTextComponent textComponent) {
this.textComponent = textComponent;
}
public void write(int b) {
synchronized(out) {
out.write(b);
}
}
public void flush() {
synchronized(out) {
String str = out.toString();
area.append(str);
out.reset();
}
}
}
class ButtonListener extends AbstractAction {
public void actionPerformed(ActionEvent e) {
String command = text.getText();
try {
area.setText("");
int exitValue = execute(command, streamArea);
JOptionPane.showMessageDialog(frame, "exitValue="+exitValue);
} catch (IOException ex) {
ex.printStackTrace();
JOptionPane.showMessageDialog(frame, "エラーが発生しました"+ex);
}
}
}
public static void main(String[] args) {
new ProcessOnSwing();
}
}
Ant はあれだけ多くのタスクに対応しているので、参考になるソースがたくさんありそうです。Antはツールですが、このようにライブラリとして使うのもいいかも。