JavaFX TextArea从坐标中获取插入符号位置

JavaFX TextArea从坐标中获取插入符号位置,java,javafx,textarea,javafx-8,Java,Javafx,Textarea,Javafx 8,在JavaFXTextArea中,是否可以在屏幕坐标(2double)处获取插入符号位置(一个int) 您可以在拖动处理程序中使用TextAreaSkin的getInsertionPoint方法: TextAreaSkin skin = (TextAreaSkin) target.getSkin(); int insertionPoint = skin.getInsertionPoint(event.getX(), event.getY()); target.positionCaret( in

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

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

TextAreaSkin skin = (TextAreaSkin) target.getSkin();
int insertionPoint = skin.getInsertionPoint(event.getX(),  event.getY());
target.positionCaret( insertionPoint);
但是,skin类在com.sun.javafx.*中,因此随着Java9的推出,您可能需要做一些不同的事情。没有人知道他们将打破什么,或者他们提供什么作为替代品。但是,对于Java8,它可以工作(目前)

可以将标签文本拖动到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();
            }
        });
    }
}
导入javafx.application.application;
导入javafx.event.EventHandler;
导入javafx.geometry.Insets;
导入javafx.scene.scene;
导入javafx.scene.control.Label;
导入javafx.scene.control.TextArea;
导入javafx.scene.input.ClipboardContent;
导入javafx.scene.input.DragEvent;
导入javafx.scene.input.Dragboard;
导入javafx.scene.input.MouseEvent;
导入javafx.scene.input.TransferMode;
导入javafx.scene.layout.HBox;
导入javafx.scene.paint.Color;
导入javafx.stage.stage;
导入com.sun.javafx.scene.control.skin.TextAreaSkin;
//此拖放示例的部分内容来自https://docs.oracle.com/javafx/2/drag_drop/HelloDragAndDrop.java.html
公共类TextAreaDemo扩展了应用程序{
公共静态void main(字符串[]args){
应用程序启动(args);
}
@凌驾
公共无效开始(阶段primaryStage){
标签源=新标签(“可拖动文本”);
TextArea target=新建TextArea();
target.setPrefRowCount(10);
target.setPrefColumnCount(100);
target.setWrapText(true);
target.setPrefWidth(150);
String cssDefault=“Lorem ipsum door sit amet,et bonorum pertinacia est,verear temporibus definition em an,ius cu just to legimus哲理。对手在静坐时完成,他的前相扑接吻。和他一起,你在一个完整的信号中。而倾斜的变化没有eos。”;
target.setText(cssDefault);
HBox根=新的HBox();
根起搏(10);
HBox.setMargin(来源,新插图(10,10,10,10));
HBox.setMargin(目标,新插图(10,10,10,10));
root.getChildren().addAll(源、目标);
场景=新场景(根,600,330,颜色.白色);
初级阶段。场景(场景);
primaryStage.show();
检测到source.setOnDragDetected(新的EventHandler(){
公共无效句柄(MouseeEvent事件){
/*允许任何传输模式*/
Dragboard db=source.startDragAndDrop(TransferMode.ANY);
/*在拖板上放一根绳子*/
ClipboardContent=新的ClipboardContent();
content.putString(source.getText());
db.setContent(content);
event.consume();
}
});
target.setOnDragOver(新的EventHandler(){
公共无效句柄(DrageEvent事件){
/*仅当未从同一节点拖动它时才接受它
*如果它有一个字符串数据*/
如果(event.getGestureSource()!=目标&&
event.getDragboard().haString()){
/*允许复制和移动,无论用户选择什么*/
事件.acceptTransferModes(TransferMode.COPY\u或\u MOVE);
//在拖动坐标处放置插入符号
TextAreaSkin=(TextAreaSkin)target.getSkin();
int insertionPoint=skin.getInsertionPoint(event.getX(),event.getY());
目标位置插入符号(插入点);
}
event.consume();
}
});
target.setOnDragDrop(新的EventHandler(){
公共无效句柄(DrageEvent事件){
/*如果拖板上有字符串数据,请读取并使用它*/
Dragboard db=event.getDragboard();
布尔成功=假;
if(db.hastring()){
target.insertText(target.getCaretPosition(),db.getString());
成功=真实;
}
/*让源知道字符串是否已成功删除
*转让和使用*/
事件。setDropCompleted(成功);
event.consume();
}
});
}
}
对于
TextArea
而言,此方法相当于罗兰的答案。此方法的实际区别在于它适用于
TextField
TextInputControl
的另一个子类):

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

关于Java9,Roland和我的答案仍然有效。
com.sun.javafx.scene.control.skin
com.sun.javafx.scene.text
(其中
HitInfo
类所在)正在移动到Java 9中的公共API。它们的位置将分别是
javafx.scene.control.skin
javafx.scene.text
。请参见JavaFX9的Javadocs:

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

target.requestFocus();

你能描述一下你想要达到的目标吗?我想您知道TextArea从TextInputControl继承了caretPosition()。这就是我问的原因。@VincentG是的,我知道返回当前插入符号位置的
caretPosition()
函数。我正在尝试实现拖放,以便
TreeView
中的项目可以拖动到文本的任何位置。这并不能回答问题
TextFieldSkin skin = (TextFieldSkin) target.getSkin();
HitInfo mouseHit = skin.getIndex(e.getX(), e.getY());
skin.positionCaret(mouseHit, false);
int insertionPoint = mouseHit.getInsertionIndex();
target.requestFocus();