【问题标题】:JavaFX TextArea get caret position from coordinateJavaFX TextArea 从坐标中获取插入符号位置
【发布时间】:2015-08-26 13:54:58
【问题描述】:

是否可以在 JavaFX TextArea 中的屏幕坐标 (2 double) 处获取插入符号位置 (int)?

【问题讨论】:

  • 您能描述一下您想要实现的目标吗?我猜你知道 TextArea 从 TextInputControl 继承 caretPosition()。这就是我问的原因。
  • @VincentG 是的,我知道 caretPosition() 函数返回当前插入符号的位置。我正在尝试实现拖放,以便可以将 TreeView 中的项目拖到文本的任何位置。

标签: java javafx textarea javafx-8


【解决方案1】:

您可以在拖动处理程序中使用 TextAreaSkin 的 getInsertionPoint 方法:

TextAreaSkin skin = (TextAreaSkin) target.getSkin();
int insertionPoint = skin.getInsertionPoint(event.getX(),  event.getY());
target.positionCaret( insertionPoint);

但是,皮肤类位于 com.sun.javafx.* 中,因此随着 Java 9 的推出,您可能不得不采取不同的做法。没有人知道他们会破坏什么或他们提供什么作为替代品。但是,对于 Java 8,它可以工作(目前)。

您可以将标签的文本拖到 TextArea 中的任何位置的完整示例:

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

import com.sun.javafx.scene.control.skin.TextAreaSkin;

// Parts of this drag/drop example are from https://docs.oracle.com/javafx/2/drag_drop/HelloDragAndDrop.java.html
public class TextAreaDemo extends Application {

    public static void main(String[] args) {
        Application.launch(args);
    }

    @Override
    public void start(Stage primaryStage) {

        Label source = new Label( "Draggable Text");

        TextArea target = new TextArea();
        target.setPrefRowCount(10);
        target.setPrefColumnCount(100);
        target.setWrapText(true);
        target.setPrefWidth(150);

        String cssDefault = "Lorem ipsum dolor sit amet, et bonorum pertinacia est, verear temporibus definitionem nam an, ius cu justo legimus philosophia. Adversarium complectitur at sit, his ex sumo nibh consequuntur. Et vim adhuc mnesarchum, eum in ignota integre tincidunt. Erant oblique alterum no eos.";

        target.setText(cssDefault);

        HBox root = new HBox();
        root.setSpacing(10);
        HBox.setMargin(source, new Insets(10,10,10,10));
        HBox.setMargin(target, new Insets(10,10,10,10));
        root.getChildren().addAll( source, target);

        Scene scene = new Scene(root, 600, 330, Color.WHITE);
        primaryStage.setScene(scene);
        primaryStage.show();

        source.setOnDragDetected(new EventHandler <MouseEvent>() {
            public void handle(MouseEvent event) {

                /* allow any transfer mode */
                Dragboard db = source.startDragAndDrop(TransferMode.ANY);

                /* put a string on dragboard */
                ClipboardContent content = new ClipboardContent();
                content.putString(source.getText());
                db.setContent(content);

                event.consume();
            }
        });

        target.setOnDragOver(new EventHandler <DragEvent>() {
            public void handle(DragEvent event) {

                /* accept it only if it is  not dragged from the same node 
                 * and if it has a string data */
                if (event.getGestureSource() != target &&
                        event.getDragboard().hasString()) {
                    /* allow for both copying and moving, whatever user chooses */
                    event.acceptTransferModes(TransferMode.COPY_OR_MOVE);

                    // position caret at drag coordinates 
                    TextAreaSkin skin = (TextAreaSkin) target.getSkin();
                    int insertionPoint = skin.getInsertionPoint(event.getX(),  event.getY());
                    target.positionCaret( insertionPoint);

                }

                event.consume();
            }
        });

        target.setOnDragDropped(new EventHandler <DragEvent>() {
            public void handle(DragEvent event) {

                /* if there is a string data on dragboard, read it and use it */
                Dragboard db = event.getDragboard();
                boolean success = false;
                if (db.hasString()) {
                    target.insertText( target.getCaretPosition(), db.getString());
                    success = true;
                }
                /* let the source know whether the string was successfully 
                 * transferred and used */
                event.setDropCompleted(success);
                event.consume();
            }
        });
    }
}

【讨论】:

    【解决方案2】:
    import com.sun.javafx.scene.control.skin.TextAreaSkin;
    import com.sun.javafx.scene.text.HitInfo;
    /****************************************************/
    
    TextAreaSkin skin = (TextAreaSkin) target.getSkin();
    HitInfo mouseHit = skin.getIndex(e.getX(), e.getY());
    // Now you can position caret
    skin.positionCaret(mouseHit, false, false);
    // And/or get insertion index
    int insertionPoint = mouseHit.getInsertionIndex();
    

    对于TextArea,这个方法等价于罗兰的回答。这种方法的实际区别在于它适用于TextFieldTextInputControl的另一个子类):

    TextFieldSkin skin = (TextFieldSkin) target.getSkin();
    HitInfo mouseHit = skin.getIndex(e.getX(), e.getY());
    skin.positionCaret(mouseHit, false);
    int insertionPoint = mouseHit.getInsertionIndex();
    

    不幸的是,TextFieldSkin 没有覆盖 getInsertionPoint(...) 并且父级的实现返回 0,因此替代解决方案在这里不起作用。

    关于 Java 9,Roland 和我的答案仍然有效。 包 com.sun.javafx.scene.control.skincom.sun.javafx.scene.textHitInfo 类所在的位置)正在移动到 Java 9 中的公共 API。它们的位置将分别为 javafx.scene.control.skinjavafx.scene.text。在此处查看 JavaFX 9 的 Javadocs:http://download.java.net/java/jdk9/jfxdocs/index.html

    【讨论】:

      【解决方案3】:

      要始终看到光标,请将其放在 setOnDragOver-Methode 中

      target.requestFocus();
      

      【讨论】:

      • 这没有回答问题
      猜你喜欢
      • 2013-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-31
      • 1970-01-01
      • 2016-12-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多