如何在 JavaFX 的 TextArea 实现回车发送信息而不换行,但组合键 Ctrl + Enter 换行

  JavaFX 的恼人之处在于很多基本的操作都要自己亲力亲为。在默认情况下,在 TextArea 输入回车会导致换行,但在很多场景中,我们希望它在用户输入回车不换行而改为触发信息的发送,换行则由组合键 Ctrl + Enter 来触发。在 JavaFX,这项功能没有简单直接的方法,并不是在所有的 UI 语言中都是如此,但 JavaFX 没有提供直接的 API。在不断踩坑之后,笔者终于在 JavaFX 中实现了这一功能。


实现的算法大致如下:

  1. 使用 TextArea 的处理器 onKeyPressed 来监听 TextArea 的键盘输入事件。

  2. 如果监听到用户输入了回车,作如下判断:

    1. 如果用户输入的不是组合键 Ctrl + Enter,去掉刚刚输入的换行符,然后将文本发送。此时可以选择清空文本框的内容还是保持文本框的内容不变。然后本算法结束。

    2. 如果用户输入的是组合键 Ctrl + Enter,在光标处插入换行符,然后将光标移至到换行符之后。然后本算法结束。

  3. 如果用户没有输入回车,什么也不做,本算法结束。


主要的注意事项如下:

  • 文本框光标的范围是 [0, length]。因为光标指向文字左右及之间的空隙,而空隙的数量比文字多 1。

  • 处理器 onKeyPressed 的回调方法是在用户按下按键(还没释放之前)就马上触发。

  • TextArea 不认为输入的组合键为单独依次这些键的效果之和。这意味着,在按下但不松开 Ctrl 键之后,输入 Enter 时,输入的文本不会包含换行符,因为 TextArea 不认为此时输入的是 Enter。但如果依次按下(不松开) aEnter,则输入的文本为 a\n

  • 在 onKeyPressed 的回调方法中,当用户输入的是普通的按键时,光标的位置为输入该字符之前的位置(刚刚输入的字符尚未在文本框中生效)。如果用户输入的是特殊的按键(如 Ctrl、Alt 、Enter 等),光标的位置为此键生效之后光标的位置。这意味着,如果输入的是 Enter,则当 onKeyPressed 的回调方法触发时,文本框中不仅包含换行符,而光标在该换行符之后。

  • 在拼接光标两侧的文本时,Enter 与组合键 Ctrl + Enter 的光标位置与文本内容均有差异。对于 Enter,需要清除换行符,而输入的换行符位于光标的左边。对于组合键 Ctrl + Enter,不仅要插入换行符,还要将光标的位置右移。

  • Windows 会将回车解释成 \n\r,但 TextArea 清除文本中所有的 \r。换句话说,当在 Windows 输入回车时,实际上输入的是 \n\r。但当向 TextArea 输入 \n\r 时,TextArea 会移除所有的 \r。从 TextArea 得到的字符串中不会包含任何 \r

  • 方法 keyEvent.isControlDown() 并不是用来判断触发 onKeyPressed 的按键(刚刚按下的按键)是不是键 Ctrl ,而是用来判断,在调用方法 keyEvent.isControlDown() 时,已经按下且未松开的按键含不含键 Ctrl。因此,如果使用该方法,就无需自行记录用户按下与释放的每一个键了。


核心代码如下:(FXML 与 FXML 的控制器的代码)

TextSend.fxml

<?xml version="1.0" encoding="UTF-8"?><?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.Button?>
<?import javafx.geometry.Insets?><VBox alignment="CENTER" spacing="20.0" xmlns:fx="http://javafx.com/fxml"fx:controller="org.wangpai.demo.textsend.TextSendController"><padding><Insets bottom="20.0" left="20.0" right="20.0" top="20.0"/></padding><TextArea prefHeight="200" prefWidth="200" fx:id="textArea" onKeyPressed="#onKeyPressedTextArea"/><Button onAction="#onActionButton" text="发送(S)"/>
</VBox>

TextSendController.java

package org.wangpai.demo.textsend;import javafx.fxml.FXML;
import javafx.event.ActionEvent;
import javafx.scene.control.TextArea;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;public class TextSendController {@FXMLprivate TextArea textArea;@FXMLpublic void onKeyPressedTextArea(KeyEvent keyEvent) {// 如果按下了回车键if (keyEvent.getCode() == KeyCode.ENTER) {// 获得此时的光标位置。此位置为刚刚输入的换行符之后var caretPosition = this.textArea.getCaretPosition();// 如果已经按下的按键中包含 Control 键if (!keyEvent.isControlDown()) { // 如果输入的不是组合键 `Ctrl+Enter`,去掉换行符,然后将文本发送// 获得输入文本,此文本包含刚刚输入的换行符var text = this.textArea.getText();// 获得换行符两边的文本var front = text.substring(0, caretPosition - 1);var end = text.substring(caretPosition);this.textArea.setText(front + end);this.onActionButton(null); // 模拟发送/*----- 如果希望发送后保留输入框文本,需要只使用下面这行代码,然后去掉清除文本框的代码 -------*/// this.textArea.positionCaret(caretPosition - 1);} else {// 获得输入文本,此文本不包含刚刚输入的换行符var text = this.textArea.getText();// 获得光标两边的文本var front = text.substring(0, caretPosition);var end = text.substring(caretPosition);// 在光标处插入换行符this.textArea.setText(front + System.lineSeparator() + end);// 将光标移至换行符this.textArea.positionCaret(caretPosition + 1);}}}/*** 模拟的发送方法*/@FXMLpublic void onActionButton(ActionEvent event) {System.out.println("正在发送信息...");System.out.println(this.textArea.getText());this.textArea.requestFocus();/*----- 如果希望发送后清除输入框文本,使用下面这行代码 -------*/this.textArea.clear();}
}

示例程序运行截图如下:

笔者的运行环境:

  • JDK 17.0.1

  • JavaFX 17.0.1

  • IntelliJ IDEA 2021.2.2 (Ultimate Edition)




完整的代码:https://gitcode.net/wangpaiblog/20211124-textsend


如何在 JavaFX 的 TextArea 实现回车发送信息而不换行,但组合键 Ctrl + Enter 换行相关推荐

  1. 仿微信div可编辑ctrl+enter换行,enter发送

    //回车发消息$scope.keyDownSend = function ($event) {var keycode = window.event?$event.keyCode:$event.whic ...

  2. java中osend,如何从java o javafx向windows任务栏发送信息

    Like when you're downloading something from Chrome the taskbar icon shows like this: i would like to ...

  3. Vue使用Alt + Enter键替代Enter键回车,enter发送消息

    因为要做一个聊天输入框,所以遇到了这个问题,因为发送消息比回车换行要常用,所以用enter键发送消息,alt+enter键回车换行 首先先给文本输入框加两个键盘事件 <textarea v-mo ...

  4. vue textarea阻止回车换行默认行为

    textarea 回车换行,导致无法使用回车发送消息 <textarea @keydown="handlePushKeyword($event)" ref="mes ...

  5. 使用Linux命令来发送信息

    使用Linux命令来发送信息 使用Linux命令来发送信息(转贴)2007-10-08 12:13 Linux发展到今天,很多功能已经可以在可视化的界面中来完成.不过在很多情况下,命令还是非常有用的, ...

  6. 如何在Google Chrome中手动设置位置信息

    如何在Google Chrome中手动设置位置信息 如果用户位于「主要城市」,通常经 IP 地址获取到的定位信息都是比较接近实际的.但是如果用户处于偏远城市或者郊区,通过 ISP 获取到的位置信息与用 ...

  7. x32dbg、x64dbg逆向微信发送信息

    一.流程分析 进行逆向之前,先分析一下微chat程序,构思一下整体思路. PC端微chat使用的协议我们可以通过对每种协议相关的API设置断点来确定是哪个协议.一般PC端客户端程序的通信协议常用的是t ...

  8. Python实现微信自动化发送信息

    需求:利用PC端微信实现自动向文件传输助手,好友等发送信息 库说明 psutil: 获取系统运行的进程和系统利用率(包括CPU.内存.磁盘.网络等)信息,用于获取进程ID pywinauto:自动化M ...

  9. Pyhton脚本发送信息给微信好友

    Pyhton脚本发送信息给微信好友 import pyautogui import pyperclip import time# 内容准备 def get_msg(): # 想要发送的内容,下一条用空 ...

最新文章

  1. MySQL LIMIT:限制查询结果的记录条数
  2. [Innost]Android深入浅出之Binder机制
  3. [其它] - 为什么中国的程序员技术偏低
  4. scala元组 数组_Scala中的数组
  5. selenium3 + java 日志
  6. 《软件工程导论》课后习题答案
  7. sql增加字段默认为0_OUP2.0:mysql乐观锁不生效
  8. java流式布局换行_自动换行的流式布局
  9. Vue快速上手笔记2 - 开发环境的搭建
  10. Microsoft JET Database Engine 错误 '80040e09' 解决方法
  11. python中正确的赋值语句_在Python中使用赋值表达式时,如何完成赋值语句“x=y:=f(x)”?...
  12. Linux使用ragel进行文本快速解析(下)
  13. Java锁原理与应用
  14. GreenPlum ANALYZE
  15. 用c语言把图像转成jpg格式,图像格式转换之BMP格式转换为JPG格式(示例代码)
  16. 联想服务器SR650升级网卡固件微码
  17. 蓝桥杯:翻转旋转变换(矩阵旋转)
  18. Tableau 多边形地图、符号地图、定义位置
  19. C++中的FILL和MEMSET(zzl) 的区分
  20. 复制淘宝店需要设置那些?

热门文章

  1. 一部手机可以对多个开发者账号开启双重认证吗?
  2. XML配置里的Bean自动装配与Bean之间的关系
  3. 数组排序(选择排序和冒泡排序)
  4. Redis 小白指南(二)- 聊聊五大类型:字符串、散列、列表、集合和有序集合...
  5. php socket的一些问题
  6. MKMapView的Span和Region深入分析
  7. Spring MVC RedirectAttributes的用法解决办法
  8. keepalived基础及使用DR模型构建一个real_server
  9. request Form request QueryString
  10. Vue 3 都 RC 了,前端的你还不来看看