2016-10-14 6 views
1

여기 내 코드입니다. 내가 직접 작성한 내용을 복사하여 붙여 넣어 문제를 직접 볼 수 있습니다.3D 장면에서 2D 노드를 선택하는 방법은 무엇입니까?

public class MyApp extends Application { 

    @Override 
    public void start(Stage stage) throws Exception { 

     Scene scene = new Scene(new MyView(), 100, 150); 
     stage.setScene(scene); 
     stage.show(); 
    } 

    private class MyView extends BorderPane { 

     MyView() { 

      GridPane board = new GridPane(); 
      int size = 3; 
      for (int i = 0; i < size*size; i++) { 
       BorderPane pane = new BorderPane(); 
       pane.setMinSize(30, 30); 
       pane.setBackground(new Background(new BackgroundFill(Color.RED, null, null))); 
       pane.setBorder(new Border(new BorderStroke(null, BorderStrokeStyle.SOLID, 
                  null, null, null))); 
       pane.setOnMousePressed(e -> { 
        PickResult pick = e.getPickResult(); 
        Pane selectedNode = (Pane) pick.getIntersectedNode(); 
        selectedNode.setBackground(new Background(new BackgroundFill(Color.GREEN, null, null))); 
       }); 
       board.add(pane, i/size, i % size); 
      } 
      Box box = new Box(20d, 20d, 20d); 
      BorderPane boardPane = new BorderPane(box, null, null, board, null); 
      Group root = new Group(boardPane); 

      SubScene scene = new SubScene(root, USE_PREF_SIZE, USE_PREF_SIZE, true, SceneAntialiasing.BALANCED); 
      scene.widthProperty().bind(widthProperty()); 
      scene.heightProperty().bind(heightProperty()); 

      setCenter(scene); 
     } 
    } 

    public static void main(String[] args) throws Exception { 

     launch(args); 
    } 
} 

나는 사각형의 그리드가있는 서브 셀을 만듭니다. 사각형을 눌러서 색을 바꿀 배경이 필요합니다. 내가 깊이 버퍼

또는 모두 장면을 설정하지 않으면 나는 boardPane

  • 에 상자를 추가하지 않을 경우

    1. 이 2 상황에서 작동합니다. 하지만 상자를 추가하고 깊이 버퍼를 설정하면 사각형에 이벤트가 수신되지 않습니다. 대신 boardPane이 수신합니다. 3D 장면에서 2D 노드와 관련이있는 것 같습니다.

      setPickOnBounds, setDepthTest, setMouseTransparent하지만 아무 것도 작동하지 않았습니다.

      해결책은 무엇입니까?

  • 답변

    1

    일단 3D 장면이 있으면 2D 노드와 같은 것이 없으며 장면 그래프의 모든 내용은 x, y 및 z 좌표를가집니다. 깊이 버퍼가 거짓으로 설정되었을 때 이전에 2D 노드로 취급되었던 것들까지도 포함 할 수 있습니다.

    루트 경계 창에 상자를 배치하면 루트 경계 창에 상자의 3D 좌표가 가정됩니다. 피킹을 위해 사용자가 정의한 상자는 3D 공간에서 z 좌표 -10에서 10까지로 표현되므로 루트 경계 창은 따기 목적으로 -10으로 정의됩니다. 루트 테두리 창 안에 배치 된 테두리 창에는 z 좌표가 정의되어 있지 않으므로 뷰어 관점에서 루트 테두리 창 뒤에있는 z 좌표가 0이됩니다.

    그래서 루트 경계 창은 클릭을 받고 있지만 이제 나머지 내용과 다른 z 평면에 있기 때문에 정의한 다른 2D 사각형 내용에 클릭이 발생하지 않습니다. 루트 경계 창은 색상이 없으므로 전혀 렌더링되지 않으므로 투명하게 처리되어야하고 클릭은 하위 노드로 전달되어야한다고 주장 할 수 있습니다.하지만 3D 피킹 알고리즘이 JavaFX가 작동합니다.

    예를 들어, 동일한 Z 플레인에서 모든 것을 가져 와서 올바르게 작동하려면 for 루프 내부에 다음 줄을 추가하십시오 : pane.setTranslateZ(-10);.

    참고 :

    root.setOnMouseClicked(System.out::println); 
    
    : 나는 (나에게 마우스 클릭의 대상과 X, Y, 클릭 할 때마다 z를 선택 결과 좌표를보고) 소스 코드에 다음 줄을 추가하여 디버깅

    내 조언은 3D 공간에서 요소 레이아웃을 시도하기 위해 2D 용도 (예 : 테두리 창) 용으로 설계된 레이아웃 창을 사용하지 않는 것입니다. JavaFX 레이아웃 창은 실제로 2D 레이아웃에만 사용됩니다. 3D 공간에서의 위치 지정을 처리하려면 Pane에서 파생되는 것보다는 Group을 사용하여 직접 좌표를 관리해야합니다. 최소한 2D 레이아웃 창에 3D 요소를 추가하지 마십시오. 결과가 혼란 스러울 수 있습니다 (발견 한대로).

    2D 및 3D 항목을 서로 다른 하위 장면에 배치하여 더 분리 할 수 ​​있습니다 (실제로는 JavaFX의 intention of the sub scene 개념이라고 생각합니다).하위 장면이 여러 개인 응용 프로그램의 예는 다음 답변에 나와 있습니다. How to create custom 3d model in JavaFX 8?

    +0

    감사합니다. 루트 패널에 이벤트를받지 못하게하고 자식 창에'pickOnBounds' 또는'setMouseTransparent'와 같은 이벤트를 수신하도록하는 방법이 있다고 생각했습니다. 실제로 실제 솔루션은 2D와 3D를 섞어서는 안된다고 보입니다. – Mark

    관련 문제