Слушайте нажатые клавиши JTextArea

Здравствуйте, я развлекаюсь, пытаясь создать свою собственную командную строку из JTextArea.

Я хотел бы иметь больше контроля над тем, как обрабатывается каретка в зависимости от того, какая клавиша нажата. Я добавил в свой JTextArea KeyListener. Моя проблема: когда нажата и обнаружена клавиша вверх, позиция каретки должна двигаться. Если я попытаюсь напечатать позицию каретки в KeyListener, я получу предыдущую. Новая только что примененная позиция будет принята во внимание после перехвата события нажатия клавиши. Что конкретно означает, предположим, что метод getCaretPosition() возвращает 15. Если я нажму стрелку вверх, я все равно получу 15 от getCaretPosition(). Только когда я выхожу из прослушивателя событий, позиция каретки изменится.

Я хотел бы получить новую позицию каретки внутри KeyListener. Текущая цель состоит в том, чтобы проверить, находится ли новая позиция каретки перед подсказкой новой строки. Если это так, то курсор вообще не должен двигаться, потому что я не хочу, чтобы эту область можно было изменить. Итак, я хотел бы получить якобы новую позицию каретки, а затем решить, хочу ли я применить эту новую позицию или нет. Как я могу это сделать?

Вот куски моего кода:

public MethodCommandLine() {
      JFrame mainFrame = new JFrame();
      mainFrame.setLayout(new FlowLayout(FlowLayout.LEFT));
      mainFrame.setLocation(200, 200);

      mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      prompt = new JTextArea(PROMPT);
      prompt.setCaretPosition(PROMPT.length());

      lastCmdPosition = prompt.getCaretPosition();

      prompt.setPreferredSize(new Dimension(300, 500));
      prompt.addKeyListener(new KeyMonitor());

      JScrollPane js = new JScrollPane(prompt);
      js.setViewportView(this.prompt);
      js.setVisible(true);

      mainFrame.getContentPane().add(js);

      mainFrame.pack();
      mainFrame.setVisible(true);

      this.formattedFields = new FormattedFields().getFField();

      init();
}



private class KeyMonitor extends KeyAdapter {
      String commandRcvd;

      public void keyPressed(KeyEvent e) {
             System.out.println("----key pressed: ." + e.getKeyChar() + ".");

          String bak = prompt.getText();
          System.out.println("\nprevious content: \n\t" + bak);

          System.out.println("\nCaret position: " + prompt.getCaretPosition());
                      // HERE: no matter which key is pressed, the former caret position will be returned. I would like to get there the NEW supposedly caret position.

          if(prompt.getCaretPosition() <= lastCmdPosition) {
              return;
          }
          if(e.getKeyCode() == KeyEvent.VK_TAB) {
              if(prompt.getText().charAt(prompt.getCaretPosition() -1) == ' ') {
                  prompt.setText(prompt.getText() + "\n" + printAvailableEntries());
              }
              else {
                  System.out.println("." + prompt.getText().charAt(prompt.getCaretPosition() -1 ) + ".");

                  System.out.println(getCurrentWord());
              }
          }

          if(e.getKeyCode() == KeyEvent.VK_DELETE || e.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
              if(prompt.getText().charAt(prompt.getCaretPosition() - 2) == '>') {
                  e.consume();
              }
          }
          if(e.getKeyCode() == KeyEvent.VK_ENTER) {


                /*
                int lines = prompt.getLineCount(); 
                System.out.println("getLineCount: " + lines);
                try {
                System.out.println("getLineEndOffset: " + prompt.getLineEndOffset(lines -1));
                System.out.println("getLineOfOffset: " + prompt.getLineOfOffset(lines -1));

                } catch (BadLocationException ex) {
                    ex.printStackTrace();
                }*/


              commandRcvd = prompt.getText().substring(lastCmdPosition);
              System.out.println("last command : ." + commandRcvd + ".");
              prompt.setText(prompt.getText() + "\n" + PROMPT);
              lastCmdPosition = prompt.getCaretPosition();
              e.consume();
         }
         if(e.getKeyCode() == KeyEvent.VK_LEFT) {
             if(prompt.getCaretPosition() -1 < lastCmdPosition) {
                 System.out.println("out : caret=" + prompt.getCaretPosition() + "\tlast=" + lastCmdPosition);
                 prompt.setCaretPosition(lastCmdPosition);
             }
             e.consume();
         }
         if(e.getKeyCode() == KeyEvent.VK_UP) {
             prompt.setCaretPosition(prompt.getCaretPosition());
         }

         System.out.println("\ncurrent content: ." + prompt.getText() + ".");

      }
}

person kaligne    schedule 09.04.2014    source источник
comment
используйте DocumentListener и/или с DocumentFilter для JTextComponents вместо KeyListener   -  person mKorbel    schedule 09.04.2014


Ответы (1)


Оберните код, вызываемый в методе слушателя, в SwingUtilities.invokeLater()

person StanislavL    schedule 09.04.2014
comment
Топ круто спасибо! Имеет ли это какое-то отношение к потоку java Event Dispatcber, например, к обновлениям JProgressBar в цикле? - person kaligne; 09.04.2014
comment
Вы спрашиваете положение каретки, но редактирование продолжается, а каретка устарела. Все, что вам нужно, это отложить проверку до окончания обработки правок. Это то, что делается обертыванием. - person StanislavL; 09.04.2014