2017-03-27 3 views
0

ComboBoxのSelectedItemプロパティのEventFilterはどのように記述できますか? This記事では、MouseEventのようなユーザーイベントについてのみ説明していますが、selectedItemプロパティの変更のEventTypeを調べることはできません。ComboBoxのEventFilterが選択されました。

スロットに資料を表示するダイアログボックスに3Dアプリケーションがあるので、質問します。そのスロットは私のコンボボックスで切り替えることができますが、選択の実際の変更が起こる前にフィルターをかけることができます。保存されていない変更があるかどうかを確認し、変更を保存したり中止するダイアログを表示します。 ComboBoxの選択が変更されたときに3Dの素材を切り替えるコンボボックス上のさまざまなリスナーがあるので、そのダイアログのアボート機能は簡単には実現できません。

「変更を保存しますか?」という他のアプローチも可能です。より適切な実装が可能です。

答えて

2

コンボボックスで値を表す別のプロパティを作成し、ユーザーが確認した場合にのみ更新することを検討してください。その後、あなたのアプリケーションの残りの部分は、そのプロパティを観察することができます。

です。

private ComboBox<MyData> combo = ... ; 

private boolean needsConfirmation = true ; 

private final ReadOnlyObjectWrapper<MyData> selectedValue = new ReadOnlyObjectWrapper<>(); 

public ReadOnlyObjectProperty<MyData> selectedValueProperty() { 
    return selectedValue.getReadOnlyProperty() ; 
} 

public final MyData getSelectedValue() { 
    return selectedValueProperty().get(); 
} 

// ... 

combo.valueProperty().addListener((obs, oldValue, newValue) -> { 

    if (needsConfirmation) { 
     // save changes dialog: 
     Dialog<ButtonType> dialog = ... ; 
     Optional<ButtonType> response = dialog.showAndWait(); 
     if (response.isPresent()) { 
      if (response.get() == ButtonType.YES) { 
       // save changes, then: 
       selectedValue.set(newValue); 
      } else if (response.get() == ButtonType.NO) { 
       // make change without saving: 
       selectedValue.set(newValue); 
      } else if (response.get() == ButtonType.CANCEL) { 
       // revert to old value, make sure we don't display dialog again: 
       // Platform.runLater() is annoying workaround required to avoid 
       // changing contents of list (combo's selected items) while list is processing change: 
       Platform.runLater(() -> { 
        needsConfirmation = false ; 
        combo.setValue(oldValue); 
        needsConfirmation = true ; 
       }); 
      } 
     } else { 
      needsConfirmation = false ; 
      combo.setValue(oldValue); 
      needsConfirmation = true ; 
     } 
    } 
}); 

今、あなたのアプリケーションは、ちょうどselectedValueProperty()を観察し、それが変化した場合に応答することができます:あなたが追加したいこれを行うには

import javafx.application.Application; 
import javafx.application.Platform; 
import javafx.beans.binding.Bindings; 
import javafx.beans.property.ReadOnlyObjectProperty; 
import javafx.beans.property.ReadOnlyObjectWrapper; 
import javafx.geometry.Insets; 
import javafx.geometry.Pos; 
import javafx.scene.Scene; 
import javafx.scene.control.ButtonType; 
import javafx.scene.control.ComboBox; 
import javafx.scene.control.Dialog; 
import javafx.scene.control.DialogPane; 
import javafx.scene.control.Label; 
import javafx.scene.layout.BorderPane; 
import javafx.stage.Stage; 

public class InterceptComboBox extends Application { 

    private ComboBox<String> combo ; 
    private boolean needsConfirmation = true ; 
    private Label view ; 
    private final ReadOnlyObjectWrapper<String> selectedValue = new ReadOnlyObjectWrapper<String>(); 

    public ReadOnlyObjectProperty<String> selectedValueProperty() { 
     return selectedValue.getReadOnlyProperty(); 
    } 

    public final String getSelectedValue() { 
     return selectedValueProperty().get(); 
    } 

    @Override 
    public void start(Stage primaryStage) { 
     combo = new ComboBox<>(); 
     combo.getItems().addAll("One", "Two", "Three"); 
     combo.setValue("One"); 
     selectedValue.set("One"); 
     view = new Label(); 
     view.textProperty().bind(Bindings.concat("This is view ", selectedValue)); 

     combo.valueProperty().addListener((obs, oldValue, newValue) -> { 
      if (needsConfirmation) { 
       SaveChangesResult saveChanges = showSaveChangesDialog(); 
       if (saveChanges.save) { 
        saveChanges(); 
       } 
       if (saveChanges.proceed) { 
        selectedValue.set(newValue); 
       } else { 
        Platform.runLater(() -> { 
         needsConfirmation = false ; 
         combo.setValue(oldValue); 
         needsConfirmation = true ; 
        }); 
       } 
      } 
     }); 

     BorderPane root = new BorderPane(view); 
     BorderPane.setAlignment(combo, Pos.CENTER); 
     BorderPane.setMargin(combo, new Insets(5)); 
     root.setTop(combo); 

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

    private void saveChanges() { 
     System.out.println("Save changes"); 
    } 

    private SaveChangesResult showSaveChangesDialog() { 
     DialogPane dialogPane = new DialogPane(); 
     dialogPane.setContentText("Save changes?"); 
     dialogPane.getButtonTypes().setAll(ButtonType.YES, ButtonType.NO, ButtonType.CANCEL); 
     Dialog<SaveChangesResult> dialog = new Dialog<>(); 
     dialog.setDialogPane(dialogPane); 
     dialog.setResultConverter(button -> { 
      if (button == ButtonType.YES) return SaveChangesResult.SAVE_CHANGES ; 
      else if (button == ButtonType.NO) return SaveChangesResult.PROCEED_WITHOUT_SAVING ; 
      else return SaveChangesResult.CANCEL ; 
     }); 
     return dialog.showAndWait().orElse(SaveChangesResult.CANCEL); 
    } 

    enum SaveChangesResult { 
     SAVE_CHANGES(true, true), PROCEED_WITHOUT_SAVING(true, false), CANCEL(false, false) ; 

     private boolean proceed ; 
     private boolean save ; 

     SaveChangesResult(boolean proceed, boolean save) { 
      this.proceed = proceed ; 
      this.save = save ; 
     } 

    } 

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

私はそれをより良いアプローチで打つことができます。 +1 – Jonah

+0

ジェームズありがとう、いつものように私が思っていなかったより良い回答ですべての私の質問に答える! +1 – 404KnowledgeNotFound

0

selectionController.selectedValueProperty().addListener((obs, oldValue, newValue) -> { 
    // respond to change... 
}); 

は、ここで(非常に単純な)SSCCEですa ChangeListenervalueProperty()ComboBox

ここに例を示します。

comboBox.valueProperty().addListener(new ChangeListener<Object>() 
{ 
    @Override 
    public void changed(ObservableValue observable, Object oldValue, Object newValue) 
    { 
     Optional<ButtonType> result = saveAlert.showAndWait(); 

     if(result.isPresent()) 
     { 
      if(result.get() == ButtonType.YES) 
      { 
       //Your Save Functionality 
       comboBox.valueProperty().setValue(newValue); 
      } 
      else 
      { 
       //Whatever 
       comboBox.valueProperty().setValue(oldValue); 
      } 
     } 
    }  
}); 
関連する問題