您好,提前感谢您的任何建议。
基本上我有一个流程窗格作为滚动窗格的内容,用于显示包含数据的用户按钮。我需要能够将它们拖动到屏幕上的任何位置,但按钮会夹在滚动窗格的边缘。我使用此代码来拖动按钮:
dataButton.setOnMousePressed(e -> {
nodeCoordinates[0] = e.getSceneX() - dataButton.getTranslateX();
nodeCoordinates[1] = e.getSceneY() - dataButton.getTranslateY();
dragData = data;
});
dataButton.setOnMouseDragged(e -> {
dataButton.setTranslateX(e.getSceneX()-nodeCoordinates[0]);
dataButton.setTranslateY(e.getSceneY()-nodeCoordinates[1]);
});
dataButton.setOnMouseReleased(e -> {
dataButton.setTranslateX(0);
dataButton.setTranslateY(0);
if(e.getButton().equals(MouseButton.SECONDARY)){
openDataPanel((Credential) data);
}
DragClearer clear= new DragClearer();//An extension of Thread for nulling a drag variable I have which gets filled with the respective data when the button is dragged
clear.start();
});
流程窗格包含每个按钮,滚动窗格不占据整个屏幕,还显示其他内容。我需要按钮返回到其原始位置,除非它们被拖动到它们所做的特定区域。有一段时间,我确实使用了内置的拖放功能,但并没有真正满足我的需要。我想说我是 javaFX 的中级人员,所以我的知识并没有那么深入。当在线搜索时,我还没有真正找到任何与我的问题类似的东西,所以我要么做错了什么,要么我肯定做错了。
再次感谢你们提供的任何建议。
这是一个示例,希望可以帮助您找到正确的方向。
此代码拍摄节点的快照,然后将节点设置为不可见。快照可拖动到
Scene
的任何部分。在目标节点上发布时,将使用原始按钮的信息重新创建按钮。我还没有尝试过,但我猜想在目标节点上发布时,您可以将按钮作为子节点添加到目标节点。
我从这里更改了代码。 @James_D here的答案可能会更好。我没有尝试他的代码。
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.ImageView;
import javafx.scene.input.*;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
/**
* Demonstrates a drag-and-drop feature.
*/
public class App extends Application
{
@Override
public void start(Stage stage)
{
//Source Buttons.
final Button boat1 = new Button("boat1");
final Button boat2 = new Button("boat2");
final Button boat3 = new Button("boat3");
final Button boat4 = new Button("boat4");
//Adding OnDragDetected to source Buttons.
setOnDragDetected(boat1);
setOnDragDetected(boat2);
setOnDragDetected(boat3);
setOnDragDetected(boat4);
//Adding onDragDone to source Buttons.
setOnDragDone(boat1);
setOnDragDone(boat2);
setOnDragDone(boat3);
setOnDragDone(boat4);
//Creating GridPane
GridPane gridPane = new GridPane();
gridPane.setVgap(5);
gridPane.setHgap(5);
gridPane.setPadding(new Insets(5, 5, 5, 5));
gridPane.setStyle("-fx-background-color: black;");
//Adding StackPane to every Cell in the GridPane and Adding the Target Events to each StackPane.
for (int i = 0; i < 6; i++) {
StackPane stackPane = new StackPane();
stackPane.setPrefSize(150, 50);
stackPane.setStyle("-fx-background-color: yellow;");
setOnDragOver(stackPane);
setOnDragEntered(stackPane);
setOnDragExited(stackPane);
setOnDragDropped(stackPane);
gridPane.add(stackPane, i / 3, i % 3);
}
HBox root = new HBox(new VBox(boat1, boat2, boat3, boat4), gridPane);
stage.setTitle("Hello Drag And Drop");
Scene scene = new Scene(root, 400, 200);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args)
{
Application.launch(args);
}
//source events handlers
public void setOnDragDetected(Button source)
{
source.setOnDragDetected((MouseEvent event) -> {
/* drag was detected, start drag-and-drop gesture*/
System.out.println("onDragDetected");
final ImageView preview = new ImageView(source.snapshot(null, null));
/* 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);
db.setDragView(preview.getImage());
source.setVisible(false);
event.consume();
});
}
public void setOnDragDone(Button source)
{
source.setOnDragDone((DragEvent event) -> {
/* the drag-and-drop gesture ended */
System.out.println("onDragDone");
/* if the data was successfully moved, clear it */
// if (event.getTransferMode() == TransferMode.MOVE) {
// source.setText("");
// }
event.consume();
});
}
//target event handlers
public void setOnDragOver(StackPane target)
{
target.setOnDragOver((DragEvent event) -> {
/* data is dragged over the target */
System.out.println("onDragOver");
/* 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);
}
event.consume();
});
}
public void setOnDragEntered(StackPane target)
{
target.setOnDragEntered((DragEvent event) -> {
/* the drag-and-drop gesture entered the target */
System.out.println("onDragEntered");
/* show to the user that it is an actual gesture target */
if (event.getGestureSource() != target
&& event.getDragboard().hasString()) {
target.setStyle("-fx-background-color: green;");
}
event.consume();
});
}
public void setOnDragExited(StackPane target)
{
target.setOnDragExited((DragEvent event) -> {
/* mouse moved away, remove the graphical cues */
target.setStyle("-fx-background-color: yellow;");
event.consume();
});
}
public void setOnDragDropped(StackPane target)
{
target.setOnDragDropped((DragEvent event) -> {
/* data dropped */
System.out.println("onDragDropped");
/* if there is a string data on dragboard, read it and use it */
Dragboard db = event.getDragboard();
boolean success = false;
if (db.hasString()) {
//target.setText(db.getString());
Button tempBoat = new Button(db.getString());
tempBoat.setMaxSize(Double.MAX_VALUE, Double.MAX_VALUE);
target.getChildren().clear();
target.getChildren().add(tempBoat);
success = true;
}
/* let the source know whether the string was successfully
* transferred and used */
event.setDropCompleted(success);
event.consume();
});
}
}