How to set carriage return to send information without line break in the TextArea of JavaFX, but press Ctrl+Enter to wrap the line

  the annoying thing about JavaFX is that many basic operations have to be done by yourself. By default, entering carriage return in TextArea will lead to line feed, but in many scenarios, we want it to trigger the sending of information instead of line feed when the user enters carriage return. Line feed is triggered by the combination of Ctrl+Enter. In JavaFX, there is no simple and direct method for this function, which is not the case in all UI languages, but JavaFX does not provide a direct API. After stepping on the pit, the author finally realized this function in JavaFX.

The implemented algorithm is roughly as follows:

  1. Use the processor onKeyPressed of TextArea to listen for keyboard input events of TextArea.

  2. If the user inputs a carriage return, make the following judgment:

    1. If the user does not enter the key combination CTRL+ENTER, remove the line break just entered, and then send the text. At this time, you can choose whether to empty the contents of the text box or keep the contents of the text box unchanged. Then the algorithm ends.

    2. If the user enters the key combination CTRL+ENTER, insert a line break at the cursor, and then move the cursor after the line break. Then the algorithm ends.

  3. If the user does not enter enter and does nothing, the algorithm ends.

The main precautions are as follows:

  • The range of the text box cursor is [0, length]. Because the cursor points to the gap in the text, and the number of gaps is 1 more than the text.

  • The callback method of the processor onKeyPressed is triggered immediately after the user presses the key (before it is released).

  • TextArea does not consider the combined keys entered as the sum of the effects of these keys in turn. This means that when you Enter after pressing but not releasing the Ctrl key, the text you Enter will not contain line breaks, because TextArea does not think you are entering Enter at this time. However, if you press (do not release) a and Enter in turn, the text entered is a\n.

  • In the callback method of onKeyPressed, when the user enters an ordinary key, the cursor position is the position before the character is entered (the character just entered has not yet taken effect in the text box). If the user enters a special key (such as Ctrl, Alt, Enter, etc.), the position of the cursor is the position of the cursor after the key takes effect. In addition,. This means that if you Enter enter, when the onKeyPressed callback method is triggered, the text box contains not only a newline character, but also the cursor after the newline character.

  • When splicing the text on both sides of the cursor, the cursor position and text content of Enter and CTRL+ENTER are different. For Enter, you need to clear the line break, and the entered line break is to the left of the cursor. For the key combination CTRL+ENTER, not only insert a line break, but also move the cursor to the right.

  • Windows interprets carriage return as \ n\r, but TextArea clears all \ r in the text. In other words, when you enter enter in windows, you actually enter \ n\r. However, when you enter \ n\r into TextArea, TextArea will remove all \ R. The string obtained from TextArea will not contain any \ R \ n.

The core code is as follows: (code of FXML and FXML controller)

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 =" send "/ >
</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 {
    @FXML
    private TextArea textArea;

    @FXML
    public void onKeyPressedTextArea(KeyEvent keyEvent) {
        // If the Enter key is pressed
        if (keyEvent.getCode() == KeyCode.ENTER) {
            // Get the cursor position at this time. This position is after the line break just entered
            var caretPosition = this.textArea.getCaretPosition();

            // If the key you have pressed contains the Control key
            if (!keyEvent.isControlDown()) { // If the key combination CTRL+ENTER is not entered, remove the newline character, and then send the text
                // Gets the input text that contains the newline character you just entered
                var text = this.textArea.getText();
                // Gets the text on both sides of the newline character
                var front = text.substring(0, caretPosition - 1);
                var end = text.substring(caretPosition);
                this.textArea.setText(front + end);
                this.onActionButton(null); // Analog transmission

                /*----- If you want to keep the input box text after sending, you need to use only the following line of code, and then remove the code that clears the text box-------*/
                // this.textArea.positionCaret(caretPosition - 1);
            } else {
                // Gets the input text that does not contain the newline character you just entered
                var text = this.textArea.getText();
                // Gets the text on both sides of the cursor
                var front = text.substring(0, caretPosition);
                var end = text.substring(caretPosition);
                // Inserts a line break at the cursor
                this.textArea.setText(front + System.lineSeparator() + end);
                // Move cursor to newline
                this.textArea.positionCaret(caretPosition + 1);
            }
        }
    }

    /**
     * Analog transmission method
     */
    @FXML
    public void onActionButton(ActionEvent event) {
        System.out.println("Sending message...");
        System.out.println(this.textArea.getText());

        this.textArea.requestFocus();
        /*----- If you want to clear the input box text after sending, use the following line of code-------*/
        this.textArea.clear();
    }
}

The screenshot of the sample program is as follows:

The author's operating environment:

  • JDK 17.0.1

  • JavaFX 17.0.1

  • IntelliJ IDEA 2021.2.2 (Ultimate Edition)

Tags: Java javafx

Posted on Tue, 23 Nov 2021 15:41:11 -0500 by michaelnorth