Javafx从TextArea拖动选定文本的问题

时间:2019-06-06 00:20:05

标签: javafx drag-and-drop textarea drag

从TextArea拖动选定的文本时遇到奇怪的问题。正确选择了文本,但是在将iam拖动到目标位置时,更改了文本选择,这会随机减少2-3个字符的选择。

这是完整的课程:

public class DnDMainController extends Application {


    ClipboardContent cb = new ClipboardContent();
    ObservableList<String> list = FXCollections.observableArrayList();
    @FXML
    private TextArea sourceText;
    @FXML
    private ListView<String> listView;
    @Override
    public void start(Stage stage) throws Exception {

        Parent root = FXMLLoader.load(getClass().getResource("/main/DnD.fxml"));
          Scene scene = new Scene(root);
          stage.setScene(scene);
          stage.setTitle("Simple Drag and Drop ExampleGame");
          stage.show();

    }

    public static void main(String[] args) {
        launch(args);
    }
    @FXML
    void _detectDrag(MouseEvent event) {
        Dragboard db = sourceText.startDragAndDrop(TransferMode.COPY);
        cb.putString(sourceText.getSelectedText());
        db.setContent(cb);
        event.consume();
    }

    @FXML
    void _dragExited(DragEvent event) {
        String st = event.getDragboard().getString();
        if (!(list.contains(st.trim()))) {
        list.add(st);
        listView.getItems().addAll(list);
    }}

}

[![gif for DnD Issue][1]][1]

我在TextField上尝试了相同的方法,并且在TextField上运行良好。但不幸的是,由于文本字符串较大,我无法使用TextField。我不知道我在做什么错...

enter image description here

FXML代码:


<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="549.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="main.DnDMainController">
   <children>
      <TextArea fx:id="sourceText" layoutY="273.0" onDragDetected="#_detectDrag" prefHeight="127.0" prefWidth="550.0" text="There was once a velveteen rabbit, and in the beginning he was really splendid. He was fat and bunchy, as a rabbit should be; his coat was spotted brown and white, he had real thread whiskers, and his ears were lined with pink sateen. On Christmas morning, when he sat wedged in the top of the Boy’s stocking, with a sprig of holly between his paws, the effect was charming." wrapText="true">
         <font>
            <Font size="19.0" />
         </font></TextArea>
      <ListView fx:id="listView" layoutY="40.0" onDragExited="#_dragExited" onMouseClicked="#_callContext" prefHeight="200.0" prefWidth="516.0" />
      <Label alignment="CENTER" contentDisplay="CENTER" layoutX="-2.0" layoutY="2.0" prefHeight="38.0" prefWidth="550.0" text="List of Words" textAlignment="CENTER" />
      <Label alignment="CENTER" contentDisplay="CENTER" layoutX="7.0" layoutY="240.0" prefHeight="32.0" prefWidth="542.0" text="Story" textAlignment="CENTER" />
   </children>
</AnchorPane>```

1 个答案:

答案 0 :(得分:0)

在尝试以一种简单的方式实现它时,我遇到了一些问题。我必须创建一个切换开关,使我可以选择文本,然后拖动文本。在拖动过程中,我注意到除非拖动开始于所选文本的末尾,否则它将不会抓取所有选定的文本。我通过在选中选定文本并将切换模式更改为拖动模式后抓取选定文本来解决该问题。下面的MCVE。

  

主要

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.Parent;

public class Main extends Application {    
    @Override
    public void start(Stage stage) throws Exception {

        Parent root = FXMLLoader.load(getClass().getResource("Test.fxml"));
          Scene scene = new Scene(root);
          stage.setScene(scene);
          stage.setTitle("Simple Drag and Drop ExampleGame");
          stage.show();
    }

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

FXML

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.ToggleButton?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane id="AnchorPane" prefHeight="583.0" prefWidth="851.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javaapplication12.TestController">
   <children>
      <ListView fx:id="listView" layoutX="326.0" layoutY="14.0" onDragDropped="#dragDropped" onDragEntered="#dragEntered" onDragOver="#dragOver" prefHeight="200.0" prefWidth="200.0" />
      <TextArea fx:id="textArea" layoutX="224.0" layoutY="274.0" onDragDetected="#dragDetected" prefHeight="247.0" prefWidth="426.0" text="There was once a velveteen rabbit, and in the beginning he was really splendid. He was fat and bunchy, as a rabbit should be; his coat was spotted brown and white, he had real thread whiskers, and his ears were lined with pink sateen. On Christmas morning, when he sat wedged in the top of the Boy’s stocking, with a sprig of holly between his paws, the effect was charming." wrapText="true" />
      <ToggleButton fx:id="tbtnDragMode" layoutX="44.0" layoutY="26.0" mnemonicParsing="false" onAction="#handleTbtnDragMode" text="Select Text Mode" />
   </children>
</AnchorPane>
  

控制器

import java.net.URL;
import java.util.ResourceBundle;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ListView;
import javafx.scene.control.TextArea;
import javafx.scene.control.ToggleButton;
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;

public class TestController implements Initializable {

    @FXML TextArea textArea;
    @FXML ListView listView;
    @FXML ToggleButton tbtnDragMode;


    ObservableList<String> list = FXCollections.observableArrayList();
    String selectedText = "";

    @Override
    public void initialize(URL url, ResourceBundle rb) {
       listView.setItems(list);

       list.add("test");
    }

    @FXML private void handleTbtnDragMode(ActionEvent actionEvent)
    {
        if(tbtnDragMode.isSelected())
        {
            System.out.println("Drag Mode On");
            tbtnDragMode.setText("Drag Mode");
            selectedText = textArea.getSelectedText().isBlank() ? "" : textArea.getSelectedText();
        }
        else {
            System.out.println("Drag Mode Off");
            tbtnDragMode.setText("Select Text Mode");
        }
    }

    @FXML
    private void dragDetected(MouseEvent event) {
        System.out.println("drag detected 1");
        System.out.println(tbtnDragMode.isSelected());
        if(tbtnDragMode.isSelected())
        {
            System.out.println("drag detected 2");
            /* drag was detected, start a drag-and-drop gesture*/
            /* allow any transfer mode */
            Dragboard db = textArea.startDragAndDrop(TransferMode.ANY);

            /* Put a string on a dragboard */
            ClipboardContent content = new ClipboardContent();
            content.putString(selectedText);
            db.setContent(content);

            event.consume();
        }

    }

    @FXML
    private void dragEntered(DragEvent event) {
        System.out.println("dragEntered");
         event.consume();
    }

    @FXML
    private void dragDropped(DragEvent event)
    {
        System.out.println("Drag dropped");
        /* data dropped */
        /* if there is a string data on dragboard, read it and use it */
        Dragboard db = event.getDragboard();
        boolean success = false;
        if (db.hasString()) {
           list.add(db.getString());
           success = true;
        }
        /* let the source know whether the string was successfully 
         * transferred and used */
        event.setDropCompleted(success);

        event.consume();
    }

    @FXML
    private void dragDone(DragEvent event) {
        /* the drag and drop gesture ended */
        /* if the data was successfully moved, clear it */
        System.out.println("drag done");
        if (event.getTransferMode() == TransferMode.MOVE) {
            //clear textarea selection
            System.out.println("drag done");
        }
        event.consume();
    }

    @FXML
    private void dragExited(DragEvent event) {
        System.out.println("dragExited");
         event.consume();
    }

    @FXML
    private void dragOver(DragEvent event) {
        /* data is dragged over the target */
        /* accept it only if it is not dragged from the same node 
         * and if it has a string data */
        System.out.println(event.getGestureSource() + " - "  + event.getTarget());
        if (event.getGestureSource() != event.getTarget() &&
                event.getDragboard().hasString()) {
            /* allow for both copying and moving, whatever user chooses */
            event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
        }

        event.consume();
    }
}