为什么我要在jtextfield中追加两次?

时间:2015-05-23 07:32:07

标签: java swing jtextfield keylistener

我查看了这段代码,我不知道出了什么问题。当我输入命令(任何输入)时,我一直得到不正确的输出。请查看我的代码的底部部分。

public class gui {

    private final static javax.swing.JFrame frame = new javax.swing.JFrame();
    private final static javax.swing.JPanel panel = new javax.swing.JPanel();
    public final static javax.swing.JTextArea outtextArea = new javax.swing.JTextArea("");
    public final static javax.swing.JTextField intextArea = new javax.swing.JTextField();

    public static void main(String[] args) {

        java.awt.Font font = new java.awt.Font(java.awt.Font.SANS_SERIF, java.awt.Font.PLAIN, 15);
        String command;

        /* Optional */
        frame.setTitle("Console");
        frame.setUndecorated(true);
        frame.getRootPane().setWindowDecorationStyle(javax.swing.JRootPane.FRAME); // COMMENT THIS OUT WHEN COMPLETE
        frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE); //if exit command, dispose() first
        frame.setBackground(java.awt.Color.BLACK);

        /* size */
        frame.setMinimumSize(new java.awt.Dimension(0b001011010100,0b000110000100));
        frame.setLocation(0,0);
        frame.setExtendedState(javax.swing.JFrame.MAXIMIZED_BOTH);

        /* Sets panel */
        panel.setBackground(java.awt.Color.PINK); // if sees pink, has error
        panel.setLayout(new java.awt.BorderLayout());
        panel.setSize(frame.getWidth(),frame.getHeight());

        /* Sets text area */
        //javax.swing.JScrollPane inscrollPane = new javax.swing.JScrollPane(intextArea);
        intextArea.setHorizontalAlignment(javax.swing.JTextField.LEFT);
        intextArea.setFont(font);
        intextArea.setBackground(java.awt.Color.BLACK);
        intextArea.setForeground(java.awt.Color.GREEN);
        intextArea.setFocusable(true);

        javax.swing.JScrollPane outscrollPane = new javax.swing.JScrollPane(outtextArea);
        outtextArea.setRows(10);
        outtextArea.setLineWrap(true);
        outtextArea.setFont(font);
        outtextArea.setBackground(java.awt.Color.BLUE);
        outtextArea.setForeground(java.awt.Color.GREEN);
        outtextArea.setEditable(false);

        /* Sets all necessary components */
        frame.add(panel);
        panel.add(outscrollPane,java.awt.BorderLayout.CENTER);
       // panel.add(inscrollPane,java.awt.BorderLayout.SOUTH);
        panel.add(intextArea,java.awt.BorderLayout.SOUTH);

        /* Adjusts components */
        frame.pack();
        frame.setVisible(true);

        //every time a command is entered, it is sent to handler and 
        //textbox should be cleared

// THIS BELOW IS WHERE THE PROBLEM LIES/////////////////////////////
        boolean keepGoing=true;
        while(keepGoing){
            command = intextArea.getText();
            String refactored;
            if(entering_a_command(command) && !command.equals("exit")){
                refactored=command.substring(0,command.length()-1);
                outtextArea.append(refactored+"\n");
                intextArea.setText("");
            }
            else if(!command.equals("exit")){//no need to read before submission
                outtextArea.append("");
                command=intextArea.getText();
            }
            else{
                outtextArea.append("EXITING\n");
                keepGoing=false;
            }
        }

    }
    /*
        Method is strictly for entering user input at appropriate time
    */
    private static boolean entering_a_command(String temp){
        //handler.print(temp);
        return temp.contains("="); //key to submit user input
    }
}

我的意见:

  • 12345 =
  • 123456 =
  • 这是地狱=
  • 这是hello =

我的预期输出:

  • 12345
  • 123456
  • 这是地狱
  • 这是你好

我的实际输出:

  • 12345
  • 12345
  • 这是地狱
  • 这是地狱

我的问题: 当我第一次输入输入时,它全部退出。当我第二次输入一个输入,一个长度大于第一次的输入时,它会自动提交,就像我按下了触发键(=)一样。

输入框是底部的黑框。要提交输入,请按' ='

1 个答案:

答案 0 :(得分:3)

问题是您正在滥用线程模型。您不应该在UI线程以外的线程中访问UI组件 - 并且像这样的紧密循环几乎总是一个坏主意。你应该阅读Swing threading model。从那个教程:

  

Swing事件处理代码在称为事件派发线程的特殊线程上运行。大多数调用Swing方法的代码也在这个线程上运行。这是必要的,因为大多数Swing对象方法都不是"线程安全":从多个线程调用它们会冒线程干扰或内存一致性错误。

相反,您应该在文本区域添加一个事件监听器。这里有加载选项,遗憾的是,其中没有一个显然是理想的。添加一个关键的监听器并处理keyTyped听起来不错 - 但是在之前,事件会在文本区域中找到关键字,这并不理想。添加文档监听器是一个很好的抽象,因为它不会影响文本的更改方式(例如以编程方式) - 但是你不能在监听器内改变文档,所以你不能清楚它

作为一个起点,添加一个关键监听器和处理keyReleased至少对于简单的情况很有效。摆脱当前循环(以及非常规命名的entering_a_command方法)并将其替换为:

intextArea.addKeyListener(new java.awt.event.KeyAdapter() {
    @Override public void keyReleased(java.awt.event.KeyEvent e) {
        String command = intextArea.getText();
        if (!command.contains("=")) {
            return;
        }

        command = command.substring(0, command.length() - 1);
        if (command.equals("exit")) {
            frame.setVisible(false);
            frame.dispose();
            return;
        }
        outtextArea.append(command + "\n");
        intextArea.setText("");
    }
});