Java 像在耐心/克朗代克纸牌游戏中一样拖动节点
我在玩克朗代克游戏。逻辑在起作用。我只是在javafx的UI上遇到了问题 我一直试图在没有预期结果的情况下移动/拖动周围“表堆”中的牌。 我的卡是一个图像视图,里面有一个图像。卡片位于窗格中:Java 像在耐心/克朗代克纸牌游戏中一样拖动节点,java,javafx,draggable,Java,Javafx,Draggable,我在玩克朗代克游戏。逻辑在起作用。我只是在javafx的UI上遇到了问题 我一直试图在没有预期结果的情况下移动/拖动周围“表堆”中的牌。 我的卡是一个图像视图,里面有一个图像。卡片位于窗格中: Pane tableau = new Pane(); for (int i = 0; i < n; i++) { Image img = new Image("resources/images/" + (i + 1) + ".png"); ImageView imgView = ne
Pane tableau = new Pane();
for (int i = 0; i < n; i++) {
Image img = new Image("resources/images/" + (i + 1) + ".png");
ImageView imgView = new ImageView(img);
imgView.setY(i * 20);
//imgView Mouse Events here
tableau.getChildren().add(imgView);
}
此解决方案不起作用,因为我正在设置位置,所以释放卡时不会返回到原来的位置,并且卡与其他UI对象发生碰撞
另一次尝试:
imgView.setOnDragDetected((MouseEvent event) -> {
ClipboardContent content = new ClipboardContent();
content.putImage(img);
Dragboard db = imgView.startDragAndDrop(TransferMode.ANY);
db.setDragView(img, 35, 50);
db.setContent(content);
event.consume();
});
在这个解决方案中,问题是:卡是半透明的,就像移动一个文件一样,光标变为“否/禁止”,但除此之外,它工作得很好:没有碰撞,如果我松开鼠标,卡就会回到原来的位置。
另一个问题是,我不知道是否可以使用此解决方案移动多张卡
我的最后一个问题是,如何将一个节点(在本例中是ImageView)或一组节点从一堆移动到另一堆,就像在纸牌游戏中一样?要知道原始卡的位置,您应该在鼠标处理程序中使用(和Y)而不是setLayoutX。因此,当用户释放卡片时,您可以简单地调用一个转换,让卡片飞回布局位置。如果用户在有效位置释放卡,则将平移坐标设置为0,并更改布局位置或使用 如果你想使卡片半透明,你可以用e。G更改或应用CSS 顺便说一下,我不会使用剪贴簿内容,它似乎不适合你的需要 您可以使用鼠标处理代码移动多个对象。您只需将平移同时应用于多个对象。拖动一堆时,确定选定卡片顶部的卡片,并将转换应用于所有卡片
下面是一个简单的示例,向您展示它的外观 java,您将使用ImageView
public class Card extends Rectangle {
static Random rand = new Random();
public Card() {
setWidth(100);
setHeight(200);
Color color = createRandomColor();
setStroke(color);
setFill( color.deriveColor(1, 1, 1, 0.4));
}
public static Color createRandomColor() {
int max = 200;
Color color = Color.rgb( (int) (rand.nextDouble() * max), (int) (rand.nextDouble() * max), (int) (rand.nextDouble() * max));
return color;
}
}
java,应用程序
public class Game extends Application {
static List<Card> cardList = new ArrayList<>();
@Override
public void start(Stage primaryStage) {
MouseGestures mg = new MouseGestures();
Group root = new Group();
for( int i=0; i < 10; i++) {
Card card = new Card();
card.relocate( i * 20, i * 10);
mg.makeDraggable(card);
cardList.add( card);
}
root.getChildren().addAll( cardList);
Scene scene = new Scene( root, 1600, 900);
primaryStage.setScene( scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
// TODO: don't use a static method, I only added for the example
public static List<Card> getSelectedCards( Card currentCard) {
List<Card> selectedCards = new ArrayList<>();
int i = cardList.indexOf(currentCard);
for( int j=i + 1; j < cardList.size(); j++) {
selectedCards.add( cardList.get( j));
}
return selectedCards;
}
}
公共类游戏扩展应用{
静态列表cardList=newarraylist();
@凌驾
公共无效开始(阶段primaryStage){
MouseGestures mg=新的MouseGestures();
组根=新组();
对于(int i=0;i<10;i++){
卡片=新卡片();
重新安置卡(i*20,i*10);
mg.makeDraggable(卡片);
卡片列表。添加(卡片);
}
root.getChildren().addAll(cardList);
场景=新场景(根,1600900);
初级阶段。场景(场景);
primaryStage.show();
}
公共静态void main(字符串[]args){
发射(args);
}
//TODO:不要使用静态方法,我只为示例添加了
公共静态列表getSelectedCards(卡当前卡){
列出所选卡片=新建ArrayList();
int i=cardList.indexOf(当前卡);
对于(int j=i+1;j
java,鼠标处理机制
public class MouseGestures {
final DragContext dragContext = new DragContext();
public void makeDraggable(final Node node) {
node.setOnMousePressed(onMousePressedEventHandler);
node.setOnMouseDragged(onMouseDraggedEventHandler);
node.setOnMouseReleased(onMouseReleasedEventHandler);
}
EventHandler<MouseEvent> onMousePressedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
dragContext.x = event.getSceneX();
dragContext.y = event.getSceneY();
}
};
EventHandler<MouseEvent> onMouseDraggedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
Node node = (Node) event.getSource();
double offsetX = event.getSceneX() - dragContext.x;
double offsetY = event.getSceneY() - dragContext.y;
node.setTranslateX(offsetX);
node.setTranslateY(offsetY);
// same for the other cards
List<Card> list = Game.getSelectedCards( (Card) node);
for( Card card: list) {
card.setTranslateX(offsetX);
card.setTranslateY(offsetY);
}
}
};
EventHandler<MouseEvent> onMouseReleasedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
Node node = (Node) event.getSource();
moveToSource(node);
// same for the other cards
List<Card> list = Game.getSelectedCards( (Card) node);
for( Card card: list) {
moveToSource(card);
}
// if you find out that the cards are on a valid position, you need to fix it, ie invoke relocate and set the translation to 0
// fixPosition( node);
}
};
private void moveToSource( Node node) {
double sourceX = node.getLayoutX() + node.getTranslateX();
double sourceY = node.getLayoutY() + node.getTranslateY();
double targetX = node.getLayoutX();
double targetY = node.getLayoutY();
Path path = new Path();
path.getElements().add(new MoveToAbs( node, sourceX, sourceY));
path.getElements().add(new LineToAbs( node, targetX, targetY));
PathTransition pathTransition = new PathTransition();
pathTransition.setDuration(Duration.millis(1000));
pathTransition.setNode(node);
pathTransition.setPath(path);
pathTransition.setCycleCount(1);
pathTransition.setAutoReverse(true);
pathTransition.play();
}
/**
* Relocate card to current position and set translate to 0.
* @param node
*/
private void fixPosition( Node node) {
double x = node.getTranslateX();
double y = node.getTranslateY();
node.relocate(node.getLayoutX() + x, node.getLayoutY() + y);
node.setTranslateX(0);
node.setTranslateY(0);
}
class DragContext {
double x;
double y;
}
// pathtransition works with the center of the node => we need to consider that
public static class MoveToAbs extends MoveTo {
public MoveToAbs( Node node, double x, double y) {
super( x - node.getLayoutX() + node.getLayoutBounds().getWidth() / 2, y - node.getLayoutY() + node.getLayoutBounds().getHeight() / 2);
}
}
// pathtransition works with the center of the node => we need to consider that
public static class LineToAbs extends LineTo {
public LineToAbs( Node node, double x, double y) {
super( x - node.getLayoutX() + node.getLayoutBounds().getWidth() / 2, y - node.getLayoutY() + node.getLayoutBounds().getHeight() / 2);
}
}
}
公共类鼠标序列{
最终DragContext DragContext=新的DragContext();
public void makeDraggable(最终节点){
node.setOnMousePressed(onMousePressedEventHandler);
node.setOnMouseDragged(onMouseDraggedEventHandler);
node.setOnMouseReleased(onMouseReleasedEventHandler);
}
EventHandler onMousePressedEventHandler=neweventhandler(){
@凌驾
公共无效句柄(MouseeEvent事件){
dragContext.x=event.getSceneX();
dragContext.y=event.getSceneY();
}
};
EventHandler onMouseDraggedEventHandler=新的EventHandler(){
@凌驾
公共无效句柄(MouseeEvent事件){
Node Node=(Node)event.getSource();
double offsetX=event.getSceneX()-dragContext.x;
double offsetY=event.getSceneY()-dragContext.y;
node.setTranslateX(offsetX);
node.setTranslateY(offsetY);
//其他卡也一样
List List=Game.getSelectedCards((卡片)节点);
用于(卡片:列表){
卡.setTranslateX(offsetX);
卡.setTranslateY(offsetY);
}
}
};
EventHandler onMouseReleasedEventHandler=新的EventHandler(){
@凌驾
公共无效句柄(MouseeEvent事件){
Node Node=(Node)event.getSource();
moveToSource(节点);
//其他卡也一样
List List=Game.getSelectedCards((卡片)节点);
用于(卡片:列表){
移动资源(卡片);
}
//如果您发现卡位于有效位置,则需要修复它,即调用重新定位并将转换设置为0
//固定位置(节点);
}
};
私有void moveToSource(节点){
double sourceX=node.getLayoutX()+node.getTranslateX();
double sourceY=node.getLayoutY()+node.getTranslateY();
double targetX=node.getLayoutX();
double targetY=node.getLayoutY();
路径路径=新路径();
path.getElements().add(新的movetoab(node、sourceX、sourceY));
path.getElements().add(newlinetoab(node,targetX,targetY));
PathTransition PathTransition=新的PathTransition();
路径转换.setDuration(Duration.millis(1000));
setNode(节点);
设置路径(路径);
pathTransition.setCycleCount(1);
path transition.setAutoReverse(true);
pathTransition.play();
}
/**
*将卡重新定位到当前位置,并将“平移”设置为0。
*@param节点
*/
专用空心固定位置(节点){
double x=node.getTranslateX();
double y=node.getTranslateY();
重新定位(node.getLayoutX()+x,node.getLayoutY()+y);
node.setTranslateX(0);
public class MouseGestures {
final DragContext dragContext = new DragContext();
public void makeDraggable(final Node node) {
node.setOnMousePressed(onMousePressedEventHandler);
node.setOnMouseDragged(onMouseDraggedEventHandler);
node.setOnMouseReleased(onMouseReleasedEventHandler);
}
EventHandler<MouseEvent> onMousePressedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
dragContext.x = event.getSceneX();
dragContext.y = event.getSceneY();
}
};
EventHandler<MouseEvent> onMouseDraggedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
Node node = (Node) event.getSource();
double offsetX = event.getSceneX() - dragContext.x;
double offsetY = event.getSceneY() - dragContext.y;
node.setTranslateX(offsetX);
node.setTranslateY(offsetY);
// same for the other cards
List<Card> list = Game.getSelectedCards( (Card) node);
for( Card card: list) {
card.setTranslateX(offsetX);
card.setTranslateY(offsetY);
}
}
};
EventHandler<MouseEvent> onMouseReleasedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
Node node = (Node) event.getSource();
moveToSource(node);
// same for the other cards
List<Card> list = Game.getSelectedCards( (Card) node);
for( Card card: list) {
moveToSource(card);
}
// if you find out that the cards are on a valid position, you need to fix it, ie invoke relocate and set the translation to 0
// fixPosition( node);
}
};
private void moveToSource( Node node) {
double sourceX = node.getLayoutX() + node.getTranslateX();
double sourceY = node.getLayoutY() + node.getTranslateY();
double targetX = node.getLayoutX();
double targetY = node.getLayoutY();
Path path = new Path();
path.getElements().add(new MoveToAbs( node, sourceX, sourceY));
path.getElements().add(new LineToAbs( node, targetX, targetY));
PathTransition pathTransition = new PathTransition();
pathTransition.setDuration(Duration.millis(1000));
pathTransition.setNode(node);
pathTransition.setPath(path);
pathTransition.setCycleCount(1);
pathTransition.setAutoReverse(true);
pathTransition.play();
}
/**
* Relocate card to current position and set translate to 0.
* @param node
*/
private void fixPosition( Node node) {
double x = node.getTranslateX();
double y = node.getTranslateY();
node.relocate(node.getLayoutX() + x, node.getLayoutY() + y);
node.setTranslateX(0);
node.setTranslateY(0);
}
class DragContext {
double x;
double y;
}
// pathtransition works with the center of the node => we need to consider that
public static class MoveToAbs extends MoveTo {
public MoveToAbs( Node node, double x, double y) {
super( x - node.getLayoutX() + node.getLayoutBounds().getWidth() / 2, y - node.getLayoutY() + node.getLayoutBounds().getHeight() / 2);
}
}
// pathtransition works with the center of the node => we need to consider that
public static class LineToAbs extends LineTo {
public LineToAbs( Node node, double x, double y) {
super( x - node.getLayoutX() + node.getLayoutBounds().getWidth() / 2, y - node.getLayoutY() + node.getLayoutBounds().getHeight() / 2);
}
}
}