今回は標準入力コンポーネントもGUIに組み込んでみます。
最初は、てっきり InputStreamを実装しなければいけないのかと思い、ByteArrayInputStreamを継承して、なんちゃらかんちゃらとがんばっていました。
10時間くらいww
ググったり…
ByteArrayInputStreamのソースコード読んだり…
System.in.read()をデバックしてF5連打したり…
しかし実際は、これ↓でいいみたい。InputStreamを実装する必要なんて無かったし…ORZ
System.setIn(new ByteArrayInputStream(this.getText().getBytes()));
あとは、テキストエリアに文字を入力して、ボタンが押されたらこいつを呼び出してやればオッケー。
・メモ:気になったこと
今回作った入力コンポーネントだと、ボタンが押されるたびに ByteArrayInputStreamのインスタンスを作っているのだけど、いいのかな?インスタンスが参照されなくなったらガベージコレクションが発動するからいいと思うのだが…。
以下が、今回作ったプログラムです。
入力コンポーネント
import java.awt.*;
import java.io.*;
import javax.swing.JTextArea;
public class InputTextArea extends JTextArea {
public InputTextArea() throws HeadlessException {
super();
this.setEditable(true);
}
public void setToSystemIn() {
System.setIn(new ByteArrayInputStream(this.getText().getBytes()));
}
}
出力コンポーネント
import java.awt.*;
import java.io.*;
import javax.swing.JTextArea;
public class OutputTextArea extends JTextArea {
private TextAreaOutputStream out;
private PrintStream printStream;
public OutputTextArea() throws HeadlessException {
super();
this.setEditable(false);
out = new TextAreaOutputStream(this);
printStream = new PrintStream(this.getOut());
}
public void setToSystemOut() {
System.setOut(getPrintStream());
}
public void setToSystemErr() {
System.setErr(new PrintStream(out));
}
public TextAreaOutputStream getOut() {
return out;
}
public PrintStream getPrintStream() {
return printStream;
}
public void flush() {
this.append(out.toString());
out.reset();
}
}
class TextAreaOutputStream extends ByteArrayOutputStream {
private OutputTextArea textarea;
public TextAreaOutputStream(OutputTextArea textarea) {
super();
this.textarea = textarea;
}
public synchronized void write(byte[] b, int off, int len) {
super.write(b, off, len);
textarea.flush();
}
public synchronized void write(int b) {
super.write(b);
textarea.flush();
}
public void write(byte[] b) throws IOException {
super.write(b);
textarea.flush();
}
}
GUIウインドウ
package gui1;
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
public class Window extends JFrame implements ActionListener, Runnable {
BufferedReader reader;
private String putdata;
/** コンポーネントの宣言 */
private JPanel panel1;
private InputTextArea inputTextArea;
private JButton button1;
private JPanel panel2;
private OutputTextArea outputTextArea;
private JPanel panel3;
private JButton button31;
private JButton button32;
private JButton button33;
/** コンポーネントのサイズ */
// frameの高さと幅のサイズ
private static final int FRAME_HEIGHT = 350;
private static final int FRAME_WIDTH = 310;
// containerの高さと幅のサイズ
private static final int CONTAINER_HEIGHT = 350;
private static final int CONTAINER_WIDTH = 310;
// panel1の高さと幅のサイズ
private static final int PANEL1_HEIGHT = 30;
private static final int PANEL1_WIDTH = 300;
// panel2の高さと幅のサイズ
private static final int PANEL2_HEIGHT = 250;
private static final int PANEL2_WIDTH = 300;
Window() {
inputTextArea = new InputTextArea();
outputTextArea = new OutputTextArea();
outputTextArea.setToSystemOut();
}
public void Display() {
setTitle("sample");// タイトル
setBounds(0, 0, FRAME_WIDTH, FRAME_HEIGHT);// Windowの大きさ
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// フレームを閉じたときプログラムを終了
try {// 外観をWindows風に設定
UIManager
.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
SwingUtilities.updateComponentTreeUI(this);
} catch (Exception e) {
e.printStackTrace();
}
// Containerを生成(nullLayout)
Container container = getContentPane();
container.setLayout(null);
container.setBounds(0, 0, CONTAINER_WIDTH, CONTAINER_HEIGHT);
panel1 = new JPanel(new GridLayout(1, 2));
panel1.setBounds(0, 0, PANEL1_WIDTH, PANEL1_HEIGHT);
button1 = new JButton("Put");
inputTextArea.setBounds(panel1.getVisibleRect());// textAreaをpanel1の位置と大きさに適合させる
inputTextArea.setLineWrap(true);// テキストエリアの幅で文字列を折り返す
panel1.add(new JScrollPane(inputTextArea));
panel1.add(button1);
button1.addActionListener(this);
// TextArea用のPanel
panel2 = new JPanel(new GridLayout(1, 1));
panel2.setBounds(0, PANEL1_HEIGHT, PANEL2_WIDTH, PANEL2_HEIGHT);
outputTextArea.setBounds(panel2.getVisibleRect());
outputTextArea.setLineWrap(true);
panel2.add(new JScrollPane(outputTextArea));
// Button用のPanel
panel3 = new JPanel(new GridLayout(1, 3));
panel3.setBounds(0, PANEL2_HEIGHT + PANEL1_HEIGHT, PANEL1_WIDTH,
PANEL1_HEIGHT);
button31 = new JButton("Get");
button32 = new JButton("button2");
button33 = new JButton("button3");
panel3.add(button31);
panel3.add(button32);
panel3.add(button33);
// ボタンにアクションリスナーを付加
button31.addActionListener(this);
button32.addActionListener(this);
button33.addActionListener(this);
// containerにパネルを追加
container.add(panel1);
container.add(panel2);
container.add(panel3);
setVisible(true); // ウインドウを見えるようにする
}
public void actionPerformed(ActionEvent ae) {
if (ae.getSource() == button1) {
inputTextArea.setToSystemIn();
reader = new BufferedReader(new InputStreamReader(System.in));
try {
putdata = reader.readLine();
} catch (IOException e) {
e.printStackTrace();
}
} else if (ae.getSource() == button31) {
System.out.println(putdata);
} else if (ae.getSource() == button32) {
System.out.println("button3が押されました。");
} else if (ae.getSource() == button33) {
System.out.println("button3が押されました。");
}
}
public void run() {
Display();
}
public static void main(String[] args) {
Window window = new Window();
new Thread(window).start();
}
}