如何在 JavaFX 的 TextArea 实现回车发送信息而不换行,但组合键 Ctrl + Enter 换行
如何在 JavaFX 的 TextArea 实现回车发送信息而不换行,但组合键 Ctrl + Enter 换行
JavaFX 的恼人之处在于很多基本的操作都要自己亲力亲为。在默认情况下,在 TextArea 输入回车会导致换行,但在很多场景中,我们希望它在用户输入回车不换行而改为触发信息的发送,换行则由组合键 Ctrl + Enter
来触发。在 JavaFX,这项功能没有简单直接的方法,并不是在所有的 UI 语言中都是如此,但 JavaFX 没有提供直接的 API。在不断踩坑之后,笔者终于在 JavaFX 中实现了这一功能。
实现的算法大致如下:
使用 TextArea 的处理器 onKeyPressed 来监听 TextArea 的键盘输入事件。
如果监听到用户输入了回车,作如下判断:
如果用户输入的不是组合键
Ctrl + Enter
,去掉刚刚输入的换行符,然后将文本发送。此时可以选择清空文本框的内容还是保持文本框的内容不变。然后本算法结束。如果用户输入的是组合键
Ctrl + Enter
,在光标处插入换行符,然后将光标移至到换行符之后。然后本算法结束。
如果用户没有输入回车,什么也不做,本算法结束。
主要的注意事项如下:
文本框光标的范围是 [0, length]。因为光标指向文字左右及之间的空隙,而空隙的数量比文字多 1。
处理器 onKeyPressed 的回调方法是在用户按下按键(还没释放之前)就马上触发。
TextArea 不认为输入的组合键为单独依次这些键的效果之和。这意味着,在按下但不松开 Ctrl 键之后,输入 Enter 时,输入的文本不会包含换行符,因为 TextArea 不认为此时输入的是 Enter。但如果依次按下(不松开)
a
、Enter
,则输入的文本为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 换行相关推荐
- 仿微信div可编辑ctrl+enter换行,enter发送
//回车发消息$scope.keyDownSend = function ($event) {var keycode = window.event?$event.keyCode:$event.whic ...
- java中osend,如何从java o javafx向windows任务栏发送信息
Like when you're downloading something from Chrome the taskbar icon shows like this: i would like to ...
- Vue使用Alt + Enter键替代Enter键回车,enter发送消息
因为要做一个聊天输入框,所以遇到了这个问题,因为发送消息比回车换行要常用,所以用enter键发送消息,alt+enter键回车换行 首先先给文本输入框加两个键盘事件 <textarea v-mo ...
- vue textarea阻止回车换行默认行为
textarea 回车换行,导致无法使用回车发送消息 <textarea @keydown="handlePushKeyword($event)" ref="mes ...
- 使用Linux命令来发送信息
使用Linux命令来发送信息 使用Linux命令来发送信息(转贴)2007-10-08 12:13 Linux发展到今天,很多功能已经可以在可视化的界面中来完成.不过在很多情况下,命令还是非常有用的, ...
- 如何在Google Chrome中手动设置位置信息
如何在Google Chrome中手动设置位置信息 如果用户位于「主要城市」,通常经 IP 地址获取到的定位信息都是比较接近实际的.但是如果用户处于偏远城市或者郊区,通过 ISP 获取到的位置信息与用 ...
- x32dbg、x64dbg逆向微信发送信息
一.流程分析 进行逆向之前,先分析一下微chat程序,构思一下整体思路. PC端微chat使用的协议我们可以通过对每种协议相关的API设置断点来确定是哪个协议.一般PC端客户端程序的通信协议常用的是t ...
- Python实现微信自动化发送信息
需求:利用PC端微信实现自动向文件传输助手,好友等发送信息 库说明 psutil: 获取系统运行的进程和系统利用率(包括CPU.内存.磁盘.网络等)信息,用于获取进程ID pywinauto:自动化M ...
- Pyhton脚本发送信息给微信好友
Pyhton脚本发送信息给微信好友 import pyautogui import pyperclip import time# 内容准备 def get_msg(): # 想要发送的内容,下一条用空 ...
最新文章
- MySQL LIMIT:限制查询结果的记录条数
- [Innost]Android深入浅出之Binder机制
- [其它] - 为什么中国的程序员技术偏低
- scala元组 数组_Scala中的数组
- selenium3 + java 日志
- 《软件工程导论》课后习题答案
- sql增加字段默认为0_OUP2.0:mysql乐观锁不生效
- java流式布局换行_自动换行的流式布局
- Vue快速上手笔记2 - 开发环境的搭建
- Microsoft JET Database Engine 错误 '80040e09' 解决方法
- python中正确的赋值语句_在Python中使用赋值表达式时,如何完成赋值语句“x=y:=f(x)”?...
- Linux使用ragel进行文本快速解析(下)
- Java锁原理与应用
- GreenPlum ANALYZE
- 用c语言把图像转成jpg格式,图像格式转换之BMP格式转换为JPG格式(示例代码)
- 联想服务器SR650升级网卡固件微码
- 蓝桥杯:翻转旋转变换(矩阵旋转)
- Tableau 多边形地图、符号地图、定义位置
- C++中的FILL和MEMSET(zzl) 的区分
- 复制淘宝店需要设置那些?
热门文章
- 一部手机可以对多个开发者账号开启双重认证吗?
- XML配置里的Bean自动装配与Bean之间的关系
- 数组排序(选择排序和冒泡排序)
- Redis 小白指南(二)- 聊聊五大类型:字符串、散列、列表、集合和有序集合...
- php socket的一些问题
- MKMapView的Span和Region深入分析
- Spring MVC RedirectAttributes的用法解决办法
- keepalived基础及使用DR模型构建一个real_server
- request Form request QueryString
- Vue 3 都 RC 了,前端的你还不来看看