2015-04-01 37 views
0

我希望用戶能夠在窗格周圍拖動移動圓圈。圓圈似乎沒有註冊(幾乎)沒有鼠標事件(最終定義)。我有一個空窗格相同的確切代碼,它工作得很好。另外,如果我改變JavaFX Circle對象未正確註冊鼠標事件

circle1.setOnMouseDragged 

paneForCircles.setOnMouseDragged 

它工作得很好,但它不是我想要的東西,因爲我需要操作兩個圓。有任何想法嗎 ?如果您還可以告訴我如何隱藏與相鄰元素重疊的圓的部分(如果其中心太靠近窗格邊界),我將不勝感激。

import javafx.application.Application; 
import javafx.geometry.Insets; 
import javafx.geometry.Pos; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.ContentDisplay; 
import javafx.scene.control.Label; 
import javafx.scene.control.TextField; 
import javafx.scene.layout.HBox; 
import javafx.scene.layout.Pane; 
import javafx.scene.layout.VBox; 
import javafx.scene.paint.Color; 
import javafx.scene.shape.Circle; 
import javafx.stage.Stage; 


public class Ex168 extends Application { 
@Override 
public void start(Stage primaryStage) throws Exception { 
    Circle circle1 = new Circle(30); 
    Circle circle2 = new Circle(35); 
    circle1.setCenterX(100); 
    circle1.setCenterY(100); 
    circle2.setCenterX(150); 
    circle2.setCenterY(120); 
    circle1.setStroke(Color.BLACK); 
    circle1.setFill(null); 
    circle2.setStroke(Color.BLACK); 
    circle2.setFill(null); 

    VBox vBoxForScene = new VBox(5); 
    vBoxForScene.setPadding(new Insets(5)); 
    vBoxForScene.setAlignment(Pos.TOP_CENTER); 

    Pane paneForCircles = new Pane(); 
    paneForCircles.setStyle("-fx-border-color: black"); 
    vBoxForScene.heightProperty().addListener(ov -> paneForCircles.setPrefHeight(vBoxForScene.heightProperty().divide(1.2).doubleValue())); 
    paneForCircles.setPrefHeight(300); 
    HBox hBoxForFields = new HBox(5); 
    hBoxForFields.setAlignment(Pos.CENTER); 
    hBoxForFields.setSpacing(5); 

    // VBofForLeftFields 
    VBox vBoxForLeftFields = new VBox(5); 
    vBoxForLeftFields.setAlignment(Pos.CENTER_LEFT); 
    Label lblCircle1 = new Label("Enter Circle 1 info"); 
    lblCircle1.setAlignment(Pos.TOP_LEFT); 
    TextField tfCircle1CenterX = new TextField(); 
    tfCircle1CenterX.textProperty().bind(circle1.centerXProperty().asString()); 
    TextField tfCircle1CenterY = new TextField(); 
    tfCircle1CenterY.textProperty().bind(circle1.centerYProperty().asString()); 
    TextField tfCircle1Radius = new TextField(); 
    tfCircle1Radius.textProperty().bind(circle1.radiusProperty().asString()); 
    tfCircle1CenterX.setPrefColumnCount(5); 
    tfCircle1Radius.setPrefColumnCount(5); 
    tfCircle1CenterY.setPrefColumnCount(5); 
    Label lblCenterX = new Label("Center x:", tfCircle1CenterX); 
    Label lblCenterY = new Label("Center x:", tfCircle1CenterY); 
    Label lblCircle1Radius= new Label("Radius: ", tfCircle1Radius); 
    lblCenterX.setContentDisplay(ContentDisplay.RIGHT); 
    lblCenterY.setContentDisplay(ContentDisplay.RIGHT); 
    lblCircle1Radius.setContentDisplay(ContentDisplay.RIGHT); 

    //VBoxForRightFields 
    VBox vBoxForRightFields = new VBox(5); 
    Label lblCircle2 = new Label("Enter Circle 2 info"); 
    TextField tfCircle2CenterX = new TextField(); 

    TextField tfCircle2CenterY = new TextField(); 
    TextField tfCircle2Radius = new TextField(); 
    tfCircle2CenterX.setPrefColumnCount(5); 
    tfCircle2CenterX.textProperty().bind(circle2.centerXProperty().asString()); 
    tfCircle2Radius.setPrefColumnCount(5); 
    tfCircle2Radius.textProperty().bind(circle2.radiusProperty().asString()); 
    tfCircle2CenterY.setPrefColumnCount(5); 
    tfCircle2CenterY.textProperty().bind(circle2.centerYProperty().asString()); 
    Label lblCenter2X = new Label("Center x:", tfCircle2CenterX); 
    Label lblCenter2Y = new Label("Center x:", tfCircle2CenterY); 
    Label lblCircle2Radius= new Label("Radius: ", tfCircle2Radius); 
    lblCenter2X.setContentDisplay(ContentDisplay.RIGHT); 
    lblCenter2Y.setContentDisplay(ContentDisplay.RIGHT); 
    lblCircle2Radius.setContentDisplay(ContentDisplay.RIGHT); 
    vBoxForRightFields.getChildren().addAll(lblCircle2, lblCenter2X, lblCenter2Y, lblCircle2Radius); 

    vBoxForLeftFields.getChildren().addAll(lblCircle1, lblCenterX, lblCenterY, lblCircle1Radius); 
    hBoxForFields.getChildren().addAll(vBoxForLeftFields, vBoxForRightFields); 
    Label lblResult = new Label("Do the two circles intersect?"); 
    Button btReDrawCircles = new Button("Redraw Circles"); 
    vBoxForScene.getChildren().addAll(lblResult, paneForCircles, hBoxForFields, btReDrawCircles); 

    circle1.setOnMouseDragged(e -> { 
     System.out.println(e.getX()); 
     circle1.setCenterX(e.getX()); 
     circle1.setCenterY(e.getY()); 
    }); 

    circle2.setOnMouseDragged(e -> { 

     circle2.setCenterX(e.getX()); 
     circle2.setCenterY(e.getY()); 
    }); 

    paneForCircles.getChildren().addAll(circle1, circle2); 
    Scene scene = new Scene(vBoxForScene); 
    primaryStage.setScene(scene); 
    primaryStage.setMinHeight(400); 
    primaryStage.setMinWidth(340); 
    primaryStage.setAlwaysOnTop(true); 
    primaryStage.show(); 
    circle1.requestFocus(); 
} 

}

此代碼,另一方面,這是應該做同樣的事情,完美的作品

public class CircleDraggingSample extends Application { 
    @Override 
    public void start(Stage primaryStage) throws Exception { 
    final double RADIUS=10; 
    Pane pane = new Pane(); 
    pane.setPrefHeight(300); 
    pane.setPrefWidth(300); 
    Circle circle1 = new Circle(RADIUS); 
    circle1.setCenterX(30); 
    circle1.setCenterY(30); 

    Circle circle2 = new Circle(RADIUS); 
    circle2.setCenterX(100); 
    circle2.setCenterY(100); 

    Line line = new Line(); 

    line.endXProperty().bind(circle2.centerXProperty()); 
    line.endYProperty().bind(circle2.centerYProperty()); 

    line.startXProperty().bind(circle1.centerXProperty()); 
    line.startYProperty().bind(circle1.centerYProperty()); 

    pane.getChildren().addAll(circle1, circle2, line); 

    circle2.setOnMouseDragged(e -> { 
     circle2.setCenterX(e.getX()); 
     circle2.setCenterY(e.getY()); 
    }); 

    circle1.setOnMouseDragged(e -> { 
     circle1.setCenterX(e.getX()); 
     circle1.setCenterY(e.getY()); 
    }); 

    Scene scene = new Scene(pane); 
    primaryStage.setScene(scene); 
    primaryStage.show(); 
} 
} 

回答

1

即使你已經發布了一個例子,我寧願秀你與我的方式一般是如何完成的。有幾種方法,這是一個工程:

public class DragNodes extends Application { 

    public static List<Circle> circles = new ArrayList<Circle>(); 

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

    @Override 
    public void start(Stage primaryStage) { 

     Group root = new Group(); 

     Circle circle1 = new Circle(100, 100, 50); 
     circle1.setStroke(Color.GREEN); 
     circle1.setFill(Color.GREEN.deriveColor(1, 1, 1, 0.3)); 

     Circle circle2 = new Circle(200, 200, 50); 
     circle2.setStroke(Color.BLUE); 
     circle2.setFill(Color.BLUE.deriveColor(1, 1, 1, 0.3)); 

     Line line = new Line(); 
     line.setStrokeWidth(20); 

     // binding 
     line.startXProperty().bind(circle1.centerXProperty()); 
     line.startYProperty().bind(circle1.centerYProperty()); 
     line.endXProperty().bind(circle2.centerXProperty()); 
     line.endYProperty().bind(circle2.centerYProperty()); 

     MouseGestures mg = new MouseGestures(); 
     mg.makeDraggable(circle1); 
     mg.makeDraggable(circle2); 
     mg.makeDraggable(line); 

     root.getChildren().addAll(circle1, circle2, line); 

     primaryStage.setScene(new Scene(root, 1024, 768)); 
     primaryStage.show(); 
    } 



    public static class MouseGestures { 

     class DragContext { 
      double x; 
      double y; 
     } 

     DragContext dragContext = new DragContext(); 

     public void makeDraggable(Node node) { 
      node.setOnMousePressed(onMousePressedEventHandler); 
      node.setOnMouseDragged(onMouseDraggedEventHandler); 
      node.setOnMouseReleased(onMouseReleasedEventHandler); 
     } 

     EventHandler<MouseEvent> onMousePressedEventHandler = new EventHandler<MouseEvent>() { 

      @Override 
      public void handle(MouseEvent event) { 

       if(event.getSource() instanceof Circle) { 

        Circle circle = ((Circle) (event.getSource())); 

        dragContext.x = circle.getCenterX() - event.getSceneX(); 
        dragContext.y = circle.getCenterY() - event.getSceneY(); 

       } else { 

        Node node = ((Node) (event.getSource())); 

        dragContext.x = node.getTranslateX() - event.getSceneX(); 
        dragContext.y = node.getTranslateY() - event.getSceneY(); 

       } 
      } 
     }; 

     EventHandler<MouseEvent> onMouseDraggedEventHandler = new EventHandler<MouseEvent>() { 

      @Override 
      public void handle(MouseEvent event) { 

       if(event.getSource() instanceof Circle) { 

        Circle circle = ((Circle) (event.getSource())); 

        circle.setCenterX(dragContext.x + event.getSceneX()); 
        circle.setCenterY(dragContext.y + event.getSceneY()); 

       } else { 

        Node node = ((Node) (event.getSource())); 

        node.setTranslateX(dragContext.x + event.getSceneX()); 
        node.setTranslateY(dragContext.y + event.getSceneY()); 

       } 

      } 
     }; 

     EventHandler<MouseEvent> onMouseReleasedEventHandler = new EventHandler<MouseEvent>() { 

      @Override 
      public void handle(MouseEvent event) { 

      } 
     }; 

    } 

} 

它顯示瞭如何拖動圓圈和綁定,這樣當你拖動圈子裏被修改以及其他節點(行)。您也可以單獨拖動該行,這是一個節點,處理方式不同。

如果你仍然有問題,讓我知道。


作爲一般的音符,它始終是最好這個以瞭解哪些事件發生添加到節點:

node.addEventFilter(Event.ANY, e -> System.out.println(e)); 

,然後檢查控制檯輸出,而你在屏幕上做一些事情。


關於您的主要問題:您不能將填充設置爲空。在這種情況下,點擊事件將不會被註冊。您應該改用Color.TRANSPARENT。您可以使用上述方法驗證事件差異。

+0

非常感謝,我將不得不研究這個,我是一個完整的begginer!這似乎是一個過於複雜的解決方案,一個相當簡單的問題。令我感到困擾的是我不明白問題所在。此代碼: – 2015-04-01 17:28:21

+1

您的評論已被刪除。但是,我用一般提示更新了答案,您可以如何分析並解決事件問題。 – Roland 2015-04-01 17:34:25

+0

您也可以使用[ScenicView工具](http://fxexperience.com/scenic-view/)來調試事件。 – jewelsea 2015-04-01 17:38:11