2016-06-15 7 views
1

를 사용하지 않고 단계를 변경하는 것을 차단 사용자는 나는 다음과 같은 응용 프로그램이 있습니다.자바 FX 모달

이 단계는 두 가지 방법 중 하나를 폐쇄 할 수 있습니다

  • 오른쪽 무대를 클릭합니다.

  • 무대 외부를 ​​클릭하십시오 (초점이 맞지 않는 경우에도 처리기가 있습니다).

그러나, 가끔이 창을 사용하여 갑판에서 하나 개 이상의 카드를 선택하도록해야합니다. 적어도 하나의 카드를 선택하기 전에는 창 닫기를 허용하고 싶지 않습니다. 이 말은 MODAL을 사용하여 (My Applicaiton) 아래 스테이지에 액세스 할 수 없도록했습니다. MODAL의 문제점은 이제는 내가 그 사람이 할 수 있기를 원할 때조차 그가 무대 밖을 클릭하여 할 수있는 것처럼 그는 결코 창을 떠나지 못한다. 그는 이제 마우스 오른쪽 버튼을 클릭하여 떠날 수 있습니다. 단추를 추가 할 수는 있지만 실제로는 그렇지 않습니다.

나는 내 문제를 충분히 설명하기를 희망한다. 내가 뭐라고 권하고 싶니? MODAL없이 이전 단계로 돌아 가지 않도록 사용자를 차단할 수있는 방법이 있습니까? 스테이지가 표시된 후에도 Modality을 변경할 수 없으므로 작동하지 않습니다.

감사합니다.

답변

2

아이디어는 팝업 StageonCloseRequestProperty 속성을 사용하는 것입니다.

이 창을 닫으라는 외부 요청이있을 때 호출됩니다. 설치된 이벤트 처리기는 수신 이벤트를 사용하여 창을 닫지 못하게 할 수 있습니다. 조건 (않도록, 하나 개의 카드에서 귀하의 경우를 선택한 경우) 경우는 Stage의 폐쇄를 중단 할 수 있습니다이 속성으로

WindowEventconsume를 호출하여 충족되지 않습니다.

참고 : 문서 상태로는 다음 요청이 외부 경우에만 유효합니다, 그래서 당신이 Stageclose 메서드를 호출 할 경우, 첨부 된 리스너가 실행되지 않습니다. 이 방법을 호출하는 대신 해결 방법으로 WindowEvent.WINDOW_CLOSE_REQUEST 이벤트를 수동으로 시작할 수 있습니다.

예 :

public class PopUpApp extends Application { 

    Stage popupStage; 
    Stage primaryStage; 

    @Override 
    public void start(Stage stage) { 
     try { 
      BorderPane root = new BorderPane(); 
      Scene scene = new Scene(root, 400, 400); 
      primaryStage = stage; 

      initPopUpStage(); 

      // When the Pop-Up stage is showing, do not handle any action on the 
      // main GUI 
      root.disableProperty().bind(popupStage.showingProperty()); 

      Button b = new Button("Open deck"); 
      b.setOnAction(new EventHandler<ActionEvent>() { 

       @Override 
       public void handle(ActionEvent event) { 

        // Add some ToggleButtons to simulate the cards 
        VBox vbox = new VBox(); 
        vbox.setAlignment(Pos.CENTER); 

        List<ToggleButton> toggles = new ArrayList<ToggleButton>(); 

        for (int i = 0; i < 4; i++) { 
         ToggleButton tb = new ToggleButton("Card " + i + 1); 
         toggles.add(tb); 
        } 
        vbox.getChildren().addAll(toggles); 

        Scene sc = new Scene(vbox, 300, 300); 
        popupStage.setScene(sc); 

        // On close request check for the condition 
        popupStage.setOnCloseRequest(new EventHandler<WindowEvent>() { 

         @Override 
         public void handle(WindowEvent event) { 
          Boolean readytoClose = false; 
          for (ToggleButton toggle : toggles) { 
           if (toggle.isSelected()) { 
            readytoClose = true; 
            break; 
           } 
          } 

          // Consume the event a show a dialog 
          if (!readytoClose) { 
           event.consume(); 
           Alert alert = new Alert(AlertType.INFORMATION, 
             "At least one card has be to be selected!"); 
           alert.showAndWait(); 
          } 
         } 
        }); 

        popupStage.show(); 

       } 
      }); 

      root.setCenter(b); 

      primaryStage.setScene(scene); 
      primaryStage.show(); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    private void initPopUpStage() { 
     popupStage = new Stage(); 
     popupStage.initOwner(primaryStage); 
     popupStage.initStyle(StageStyle.UNDECORATED); 
     // On focus loss, close the window 
     popupStage.focusedProperty().addListener(new ChangeListener<Boolean>() { 

      @Override 
      public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { 

       // Rather than popupStage.close(); fire the event manually 
       if (!newValue) 
        popupStage.fireEvent(new WindowEvent(popupStage, WindowEvent.WINDOW_CLOSE_REQUEST)); 
      } 
     }); 
    } 

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

업데이트 :

주요 Stage 내가 추가 한 사용할 수없는이 줄을 만들려면 :

root.disableProperty().bind(popupStage.showingProperty()); 

이는 동안 루트 BorderPane을 해제합니다 팝업 단계가 표시됩니다. 팝업 창이 닫히 자마자 기본 창이 다시 활성화됩니다.

+0

감사합니다. 이런 종류의 기능을 위해 onCloseRequest를 사용할 수 있는지 전혀 몰랐습니다. 그래도 엄청난 문제 야. 'Modality '가 없다면 사용자는 팝업창이 나더라도 나머지 응용 프로그램과 통신 할 수 있습니다. 그들은 갑판을 50 번 클릭하고 50 개의 창을 만들 수 있습니다. 내 현재의 아이디어는 내 기본 GUI 클래스에 정적 부울 변수를 갖는 것입니다.이 변수는 "현재 표시된 창입니까?"라고 말합니다. 이 변수가 true이면 기본 스테이지에서 이벤트 핸들러를 활성화하지 마십시오. 그러나 그것은 일종의 고통입니다. 다른 아이디어? – Hatefiend

+0

답변에서 내 업데이트를 참조하십시오. – DVarga

+0

굉장합니다. 마지막 한가지. 나는 이것과 같이 보이고 숨길 수있는 여섯 개의 독특한 창을 가지고 있으며, 나는 여섯 명 모두가 그런 식으로 묶일 필요가있다. 지금은'.bind()'를 호출하면 이전의'bind'를 덮어 씁니다. 그리고 바운드 된 마지막 속성 만이 비활성화 된 속성에 영향을줍니다. 여러 항목을 어떻게 바인딩 할 수 있습니까? – Hatefiend