-1

我有一个 JFrame,其中包含一个 JPanel,其中包含一个 JTextArea。我已经成功地将 System.out 指向 JTextArea,但是当我尝试使用 Scanner(System.in) 来解析来自 JTextArea 的输入时,它甚至似乎没有加载任何内容。例如,当我构建和运行应用程序时,什么也没有发生,也没有显示任何框架。这是我的代码:

/**
 * Create the frame.
 */
public TerminalForm() {
    setTitle("Terminal");
    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    setBounds(100, 100, 570, 370);
    contentPane = new JPanel();
    contentPane.setBorder(BorderFactory.createEmptyBorder());
    setContentPane(contentPane);
    contentPane.setLayout(new BorderLayout(0, 0));

    PipedInputStream inPipe = new PipedInputStream();
    PipedInputStream outPipe = new PipedInputStream();

    System.setIn(inPipe);
    try {
        System.setOut(new PrintStream(new PipedOutputStream(outPipe), true));
    } catch (IOException e1) {
        e1.printStackTrace();
    }
    PrintWriter inWriter = null;
    try {
        inWriter = new PrintWriter(new PipedOutputStream(inPipe), true);
    } catch (IOException e) {
        e.printStackTrace();
    }

    final JTextArea txtIO = console(outPipe, inWriter);
    txtIO.setFont(new Font("Andale Mono", Font.PLAIN, 12));
    txtIO.setCaretColor(new Color(50, 205, 50));
    txtIO.getCaret().setVisible(true);
    txtIO.getCaret().setSelectionVisible(true);
    txtIO.setLineWrap(true);
    txtIO.setForeground(new Color(50, 205, 50));
    txtIO.setBackground(new Color(0, 0, 0));
    txtIO.setBorder(BorderFactory.createEmptyBorder());
    contentPane.add(txtIO);

    // 5. get some input (from JTextArea)
    Scanner s = new Scanner(System.in);
    System.out.printf("got from input: \"%s\"%n", s.nextLine());
}

public static JTextArea console(final InputStream out, final PrintWriter in) {
    final JTextArea area = new JTextArea();

    // handle "System.out"
    new SwingWorker<Void, String>() {
        @Override protected Void doInBackground() throws Exception {
            Scanner s = new Scanner(out);
            while (s.hasNextLine()) publish(s.nextLine() + "\n");
            s.close();
            return null;
        }
        @Override protected void process(List<String> chunks) {
            for (String line : chunks) area.append(line);
        }
    }.execute();

    // handle "System.in"
    area.addKeyListener(new KeyAdapter() {
        private StringBuffer line = new StringBuffer();
        @Override public void keyTyped(KeyEvent e) {
            char c = e.getKeyChar();
            if (c == KeyEvent.VK_ENTER) {
                in.println(line);
                line.setLength(0); 
            } else if (c == KeyEvent.VK_BACK_SPACE) { 
                line.setLength(line.length() - 1); 
            } else if (!Character.isISOControl(c)) {
                line.append(e.getKeyChar());
            }
        }
    });

    return area;
}
4

2 回答 2

1

如果这是我的代码,我不会让用户直接在 JTextArea 中输入,而是在 JTextArea 正下方的 JTextField 中输入(BorderLayout.SOUTH 到 JTextArea,它保存在 BorderLayout.CENTER 的 JScrollPane 中)。然后,我将通过ActionListener 通过enter 接受输入,然后打印用户在JTextArea 中输入的内容,并表明它来自用户,并通过OutputStream 或更好的PrintStream 将输入的文本发送出去。

例如,类似的东西,

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.List;
import java.util.Scanner;

import javax.swing.*;
import javax.swing.text.JTextComponent;

@SuppressWarnings("serial")
public class TerminalForm extends JPanel {
   private static final int GAP = 3;
   public static final String PRE_TEXT = "User> ";
   private JTextArea textarea;
   private JTextField textfield;

   public TerminalForm(int rows, int cols, InputStream inStream, PrintStream printStream) {
      textarea = prepareTextArea(rows, cols, inStream);
      textfield = prepareTextField(cols, printStream, textarea);

      setLayout(new BorderLayout(GAP, GAP));
      setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
      add(new JScrollPane(textarea), BorderLayout.CENTER);
      add(textfield, BorderLayout.SOUTH);
   }

   private JTextField prepareTextField(int cols, PrintStream printStream, JTextArea textArea) {
      JTextField textField = new JTextField(cols);
      textField.addActionListener(new TextFieldListener(printStream, textArea));
      return textField;
   }

   private JTextArea prepareTextArea(int rows, int cols, InputStream inStream) {
      JTextArea textArea = new JTextArea(rows, cols);
      textArea.setEditable(false);
      textArea.setFocusable(false);
      InputStreamWorker instreamWorker = new InputStreamWorker(textArea, inStream);
      instreamWorker.execute();
      return textArea;
   }

   private class TextFieldListener implements ActionListener {
      private PrintStream printStream;
      private JTextArea textArea;

      public TextFieldListener(PrintStream printStream, JTextArea textArea) {
         this.printStream = printStream;
         this.textArea = textArea;
      }

      @Override
      public void actionPerformed(ActionEvent evt) {
         JTextComponent textComponent = (JTextComponent) evt.getSource();
         String text = textComponent.getText();
         textComponent.setText("");

         printStream.println(text);
         textArea.append(TerminalForm.PRE_TEXT + text + "\n");
      }
   }

   private class InputStreamWorker extends SwingWorker<Void, String> {
      private Scanner scanner;
      private JTextArea textArea;

      private InputStreamWorker(JTextArea textArea, InputStream inStream) {
         this.textArea = textArea;
         scanner = new Scanner(inStream);
      }

      @Override
      protected Void doInBackground() throws Exception {
         while (scanner.hasNextLine()) {
            publish(scanner.nextLine());
         }
         return null;
      }

      @Override
      protected void process(List<String> chunks) {
         for (String chunk : chunks) {
            textArea.append(chunk + "\n");
         }
      }
   }

   private static void createAndShowGui(final InputStream inStream, final PrintStream printStream) {
      int rows = 20;
      int cols = 40;
      TerminalForm mainPanel = new TerminalForm(rows, cols, inStream, printStream);

      JFrame frame = new JFrame("TerminalForm2");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      final InputStream inStream = System.in;
      final PrintStream printStream = System.out;
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui(inStream, printStream);
         }
      });
   }
}
于 2013-08-24T16:20:00.133 回答
1

您没有将框架设置为可见。

于 2016-02-07T22:08:34.093 回答