標準コンソールを使用してユーザー入力を取得し、System.in および System.out からメッセージを表示するいくつかの小さなアプリケーションがあります。
ここで、これらのアプリケーションから呼び出される Swing ベースのクラスを実現したいと思います。2 つのテキスト領域を持つフレームが表示されます。 System.out へ)。実際、私はすべてを実装しました (実際には、単純なスイング ベースの GUI を作成し、イベント ディスパッチャー スレッドから起動するのはそれほど複雑ではありません。すべてを jar としてエクスポートし、元のプロジェクトにライブラリとして含める場合と同じです)。これまでに私が抱えていた唯一の問題は、標準の System.in と System.out を 2 に関連付けられているカスタムのものに交換することJTextArea
です。実際にいくつかのソリューションをオンラインで確認したところ、次の数行のコードになりました。
2 つの PipedInputStream と PrintWriter を使用します。
private final PipedInputStream inPipe = new PipedInputStream();
private final PipedInputStream outPipe = new PipedInputStream();
private PrintWriter inWriter;
次に、ストリームを交換します
System.setIn(inPipe);
System.setOut(new PrintStream(new PipedOutputStream(outPipe), true));
inWriter = new PrintWriter(new PipedOutputStream(inPipe), true);
outPipe からデータを取得するために、メソッド troughtout を使用してSwingWorker
outPipedoInBackgroud
からScanner
行を読み取り、これらの行の文字列を編集不可能な JTextArea に追加するために公開します。一方、プロンプトとして使用される JTextField からテキストを取得するためにクリックをkeyListener
チェックしVK_ENTER
ます。これが発生すると、System.out 自体を使用してテキストが表示され、以前の JTextArea に効果的に表示されるため、上記の SwingWorker が機能し、次に、同じテキスト行を inWriter ( PrintStream
System.in に関連するパイプに関連付けられたオブジェクト) に書き込んだので、元のアプリケーションに存在する Reader オブジェクトからその行を読み取ることができるはずです。
残念ながら、これは機能しないコードの唯一の部分です。実際、新しい gui コンソールを起動してからストリームを変更すると、元のアプリケーションは System.out に出力するテキストのみを表示しますが、ユーザーが書いたテキストを読みたい場合、たとえば BufferedReader または aスキャナー オブジェクトは、ストリーム内が空であるかのように何も起こりません。
これは、SwingWorker doInBackground メソッドの Scanner が原因だと思います。これは、outPipe の次の行を読み取るときに、ストリーム自体もクリーンアップするためです。この問題を解決するためのアイデアはありますか? 入力と出力を処理する新しいメソッドを作成できることはわかっていますが、この邪魔にならないアプローチを維持したいので、元のコードを編集せずに、元のアプリケーションのメイン メソッドでの GUI コンソール オブジェクトの作成の一部を行います。前もって感謝します。
更新 1
これは Console クラスで、すべてここで行われます
public class Console extends JFrame implements KeyListener
{
private JTextField prompt;
private JTextArea log;
private final PipedInputStream inPipe = new PipedInputStream();
private final PipedInputStream outPipe = new PipedInputStream();
private PrintWriter inWriter;
public Console(String title)
{
super(title);
System.setIn(inPipe);
try
{
System.setOut(new PrintStream(new PipedOutputStream(outPipe), true));
inWriter = new PrintWriter(new PipedOutputStream(inPipe), true);
}
catch(IOException e)
{
System.out.println("Error: " + e);
return;
}
JPanel p = new JPanel();
p.setLayout(null);
log = new JTextArea();
log.setEditable(false);
log.setBounds(10, 10, 345, 250);
p.add(log);
prompt = new JTextField();
prompt.setBounds(10, 270, 356, 80);
prompt.addKeyListener(this);
p.add(prompt);
getContentPane().add(p);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setSize(392, 400);
setLocationRelativeTo(null);
(new SwingWorker<Void, String>()
{
protected Void doInBackground() throws Exception
{
Scanner s = new Scanner(outPipe);
while (s.hasNextLine())
{
String line = s.nextLine();
publish(line);
}
return null;
}
@Override
protected void process(java.util.List<String> chunks)
{
for (String line : chunks)
{
if (line.length() < 1)
continue;
log.append(line.trim() + "\n");
}
}
}).execute();
}
public void execute()
{
String text = prompt.getText();
prompt.setText("");
System.out.println(text);
inWriter.print(text.trim().replaceAll("\r\n", ""));
}
@Override
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_ENTER)
execute();
}
@Override
public void keyReleased(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_ENTER)
execute();
}
@Override
public void keyTyped(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_ENTER)
execute();
}
// this is the method called from the original application
public static void setConsole(final String title)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
new Console(title);
//System.out.println("somewhat");
}
});
}
}