【问题标题】:JTextArea pressing enter adds unnecessary new lineJTextArea 按下回车会添加不必要的新行
【发布时间】:2013-11-03 08:37:28
【问题描述】:

我正在开发一个聊天应用程序,当我在聚焦 JTextArea 时按下回车按钮时,我希望它停止添加不必要的新文本行,例如,我将能够确定用户何时按下回车按钮并且没有在 JTextArea 内输入任何内容。我正在使用 KeyListener 来检测用户何时释放回车键然后发送消息。我首先尝试用空字符串 message.replaceAll("[\n]", "") 替换新的文本行并修剪消息,但是它没有用。我的方法有什么问题吗,或者我可以采用其他解决方案吗?

【问题讨论】:

  • 改用 JTextField。

标签: java swing jtextarea keylistener key-bindings


【解决方案1】:
  • 不要为此使用 JTextArea,而是使用 JTextField。
  • 然后,您可以通过为 JTextField 提供一个 ActionListener 来轻松地监听回车。
  • 我见过的大多数 Swing 聊天应用程序为此使用两个文本组件:一个 JTextArea 用于显示传入文本和您发送的文本,一个 JTextField 允许用户输入要发送的文本。
  • 通常使用 BorderLayout 一个在另一个之上。


  • 如果您绝对必须使用 JTextArea,那么您可能希望使用键绑定来捕获回车键并进行处理。查看How to use Key Bindings Tutorial


例如:

示例键绑定解决方案:

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;

import javax.swing.*;

@SuppressWarnings("serial")
public class CaptureTextAreaEnter extends JPanel {
   private static final int COLS = 30;
   private static final int VIEW_ROWS = 12;
   private static final int ENTER_ROWS = 4;
   private JTextArea chatViewArea = new JTextArea(VIEW_ROWS, COLS);
   private JTextArea chatEnterArea = new JTextArea(ENTER_ROWS, COLS);

   public CaptureTextAreaEnter() {
      setLayout(new BorderLayout());
      add(new JScrollPane(chatViewArea), BorderLayout.CENTER);
      add(new JScrollPane(chatEnterArea), BorderLayout.SOUTH);

      chatViewArea.setFocusable(false);

      chatViewArea.setWrapStyleWord(true);
      chatEnterArea.setWrapStyleWord(true);
      chatViewArea.setLineWrap(true);
      chatEnterArea.setLineWrap(true);

      // start our set up of key bindings

      // to get the correct InputMap
      int condition = WHEN_FOCUSED;  
      // get our maps for binding from the chatEnterArea JTextArea
      InputMap inputMap = chatEnterArea.getInputMap(condition);
      ActionMap actionMap = chatEnterArea.getActionMap();

      // the key stroke we want to capture
      KeyStroke enterStroke = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0);

      // tell input map that we are handling the enter key
      inputMap.put(enterStroke, enterStroke.toString());

      // tell action map just how we want to handle the enter key
      actionMap.put(enterStroke.toString(), new AbstractAction() {

         @Override
         public void actionPerformed(ActionEvent arg0) {
            String text = chatEnterArea.getText();
            chatEnterArea.setText("");
            chatViewArea.append(text + "\n");

            // *** you will want to send text to your 
            // *** PrintStream to the chat server here 
         }
      });
   }

   private static void createAndShowGui() {
      CaptureTextAreaEnter mainPanel = new CaptureTextAreaEnter();

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

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

【讨论】:

  • 好的,感谢您的回答,但是我已经注意到 JTextField 不允许换行,如何在文本字段中恢复此功能?
  • 我真的很想保持滚动垂直+线包裹,否则如果不可能,我可能会寻求 JTextArea 的解决方案
  • 完美,它通过设置自定义键绑定的方式与 JTextArea 一起使用。谢谢 :) 对于任何有同样问题的人来说,这也是一个很好的资源dreamincode.net/forums/topic/…
【解决方案2】:

这是对我的系统完美运行的解决方案。

AddTxtA.getDocument().putProperty("filterNewlines", Boolean.TRUE);

**当用户在 JTextArea 中按下“Enter”按钮时,将输入一个空格而不是新行。下面显示了两种不同情况的示例输出。

1) 没有 AddTxtA.getDocument().putProperty("filterNewlines", Boolean.TRUE);。

输出:“我的名字

是亚当。”

2) 使用 AddTxtA.getDocument().putProperty("filterNewlines", Boolean.TRUE);

输出:“我叫亚当。”

【讨论】:

    【解决方案3】:

    要替换“输入”键的标准行为,您应该使用文本区域的输入/操作映射

    参见方法registerKeyboardAction(ActionListener anAction,String aCommand,KeyStroke aKeyStroke,int aCondition)。作为动作监听器,您应该从“发送”按钮中获取动作,命令是您选择的字符串,击键是KeyStroke.getKeyStroke(KeyEvent.VK_ENTER),条件是JComponent.WHEN_FOCUSED

    【讨论】:

    • 我不同意您关于查看registerKeyboardAction 方法的建议。根据JComponent API"This method is now obsolete, please use a combination of getActionMap() and getInputMap() for similiar behavior." 再次根据我的回答更好地使用标准键绑定。
    • 为什么?此方法在内部使用 Input/Action 映射。
    • 该方法可能正在被弃用。至于为什么,我不知道。您将希望与 Java 和 Swing 的开发人员和维护人员讨论这个问题。在 Java API 中发表评论的是他们,而不是我。
    • 据我所知,这种方法从 Java 1.3 开始就已经过时了。所以我认为我们可以在未来 10 年内使用它而不会收到弃用警告;)
    • 如果您更喜欢在代码中使用过时和不推荐使用的方法,那很好,就这样吧,但是建议其他人在 SO 中这样做作为答案并不是一个好主意,尤其是当非- 存在过时和未弃用的方法。
    猜你喜欢
    • 2011-10-13
    • 1970-01-01
    • 2020-06-01
    • 2019-11-04
    • 1970-01-01
    • 1970-01-01
    • 2011-01-06
    相关资源
    最近更新 更多