今回は標準入力コンポーネントも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(); } }