2017-09-13 1 views
0

저는 다소 프로그래밍에 익숙하지 않고 OOP (2 차 Java 프로젝트 모두 지금 당장)에 익숙하지 않으며 힌트 나 도움을 좋아할 것입니다.ToggleGroup 내에서 가능한 선택 항목 수를 늘리는 방법 (예 : RadioButtons)?

저는 현재 자신의 펜 & 종이 게임을위한 캐릭터 작성 프로그램을 만들고 있습니다. GUI 부분에 JavaFX (FXML이 없으므로 SceneBuilder가 없음)을 사용하고 있습니다. JDK1.8.0_131에서 Eclipse Neon으로 작업하고 있습니다. 여기

내 문제입니다 :
TL; DR : 어떻게 ToggleGroup 내에서 가능한 선택의 수를 증가하는 방법?
사용자가 선택할 수있는 옵션 목록을 만들려고합니다. 이 목록은 약 30 가지의 다른 장점으로 구성되어 있습니다. 선택한 옵션의 최대 허용치는 문자에 따라 다르며 약 5 배 정도 다릅니다. 이미 pairs (HashMaps에 대해 알고 있습니다)의 배열을 구현했습니다. 각 항목은 이점의 이름과 비용을 나타내는 정수로 구성됩니다 그들의 가치, 그래서 그들의 비용).
목록 자체가 지금은 ToggleButtons에 대해 너무 많이 걱정하지 않는다

ScrollPane scrollAdv = new ScrollPane(); 
VBox vBoxAdv = new VBox(); 
scrollAdv.setContent(vBoxAdv); 
Pair<String, Integer>[] listAdv = info.getAdvantages(); 
for (int i = 0; i < listAdv.length; i++) { 
    String name = listAdv[i].getKey(); // delivers the 1st entry of a pair 
    int costs = listAdv[i].getValue(); // delivers the 2nd entry of a pair 
    ToggleButton toggleButton = new ToggleButton(); 
    toggleButton.setUserData(name); 
    toggleButton.setText(name + " (" + costs + ")"); 
    vBoxAdv.getChildren().add(toggleButton); 
} 

참고 통해 구현되어야하며, 그들은 쉽게 RadioButtons를 대체 할 수있다. 설명서를 올바르게 이해하면 두 가지 방법이 동일하게 작동합니다. 둘 다 ToggleGroup을 사용하여 하나의 옵션 만 선택합니다.
아마도 지금까지 짐작했지만, 사용자가 여러 옵션을 한꺼번에 선택할 수있는 기회를 제공하고 싶습니다. 나는 그것을 만들기를 원하지 않으므로, 사용자가 다른 옵션을 선택해야하고 그 사이에리스트를 재설정해야한다.

미리 읽어 주셔서 감사 드리며 도움이나 힌트를 보내 주셔서 감사합니다.

편집 : 언제든지 하나의 옵션을 선택하거나 선택 취소 할 때마다 새로 고치는 카운터를 추가하여 < 1이면 선택 사항을 차단하지만 더 나은 해결책이 있어야한다고 생각했습니다. ToggleGroup이 사용하고있는 것으로 보이는 기본 제공 제한 인 1을 늘리십시오.

+0

그래서 사용자가 몇 가지 토글 버튼 (또는 이와 유사한)을 선택할 수 있기를 원하지만 제한 사항은 얼마입니까? 예를 들어 30 개 중 0 ~ 5 개를 선택할 수 있습니다 (단 5 개 이하). 그것이 그 질문의 정확한 해석입니까? –

+0

@ James_D 네, 맞습니다. –

답변

1

한 가지 방법은 한도에 도달하면 나머지 토글을 사용 중지하는 것입니다.

import java.util.ArrayList; 
import java.util.List; 

import javafx.beans.Observable; 
import javafx.beans.binding.Bindings; 
import javafx.beans.binding.IntegerBinding; 
import javafx.beans.property.IntegerProperty; 
import javafx.beans.property.SimpleIntegerProperty; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.collections.transformation.FilteredList; 
import javafx.scene.Node ; 
import javafx.scene.control.Toggle; 

public class ToggleSet<T extends Node & Toggle> { 

    private final ObservableList<T> toggles = FXCollections.observableArrayList(t -> new Observable[] {t.selectedProperty()}); 
    private final FilteredList<T> selectedToggles = toggles.filtered(t -> ((Toggle)t).isSelected()); 
    private final IntegerProperty maximumSelectable = new SimpleIntegerProperty(0); 

    private final IntegerBinding numSelected = Bindings.size(selectedToggles); 

    public ToggleSet(int maximumSelectable) { 

     this.maximumSelectable.addListener((obs, oldMax, newMax) -> { 
      if (newMax.intValue() < numSelected.get()) { 
       List<Toggle> togglesToClear = new ArrayList<>(selectedToggles.subList(0, numSelected.get() - newMax.intValue())); 
       togglesToClear.forEach(t -> t.setSelected(false)); 
      } 
     }); 

     setMaximumSelectable(maximumSelectable); 
    } 

    public ToggleSet() { 
     this(0); 
    } 

    public ObservableList<T> getSelectedToggles() { 
     return FXCollections.unmodifiableObservableList(selectedToggles) ; 
    } 

    public IntegerProperty maximumSelectableProperty() { 
     return maximumSelectable ; 
    } 

    public final int getMaximumSelectable() { 
     return maximumSelectableProperty().get(); 
    } 

    public final void setMaximumSelectable(int maximumSelectable) { 
     maximumSelectableProperty().set(maximumSelectable); 
    } 

    public void addToggle(T toggle) { 
     if (numSelected.get() >= getMaximumSelectable()) { 
      toggle.setSelected(false); 
     } 
     toggles.add(toggle); 
     toggle.disableProperty().bind(toggle.selectedProperty().not().and(numSelected.greaterThanOrEqualTo(maximumSelectable))); 
    } 

    public void removeToggle(T toggle) { 
     toggles.remove(toggle); 
     toggle.disableProperty().unbind(); 
    } 

} 

가 여기 테스트 예입니다 : 여기에 수행하는 ToggleSet 클래스의 이전 선택이 선택되지 않은이되는 ToggleGroup, 같은 동작을합니다

import javafx.application.Application; 
import javafx.geometry.Insets; 
import javafx.scene.Scene; 
import javafx.scene.control.CheckBox; 
import javafx.scene.control.Label; 
import javafx.scene.control.RadioButton; 
import javafx.scene.control.Spinner; 
import javafx.scene.control.ToggleButton; 
import javafx.scene.layout.GridPane; 
import javafx.scene.layout.HBox; 
import javafx.stage.Stage; 

public class ToggleSetTest extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     ToggleSet<ToggleButton> toggleSet = new ToggleSet<>(5); 
     GridPane grid = new GridPane() ; 

     Spinner<Integer> maxSelectedSpinner = new Spinner<>(0, 20, 5); 
     maxSelectedSpinner.getValueFactory().valueProperty().bindBidirectional(toggleSet.maximumSelectableProperty().asObject()); 

     grid.add(new HBox(2, new Label("Maximum selected"), maxSelectedSpinner), 0, 0, 2, 1); 

     grid.addRow(1, new Label("Selection"), new Label("Include in set")); 

     for (int i = 1; i <= 20 ; i++) { 
      RadioButton button = new RadioButton("Button "+i); 
      CheckBox checkBox = new CheckBox(); 
      checkBox.selectedProperty().addListener((obs, wasChecked, isNowChecked) -> { 
       if (isNowChecked) { 
        toggleSet.addToggle(button); 
       } else { 
        toggleSet.removeToggle(button); 
       } 
      }); 
      checkBox.setSelected(true); 
      grid.addRow(i + 1, button, checkBox); 
     } 
     grid.setPadding(new Insets(10)); 
     grid.setHgap(5); 
     grid.setVgap(2); 
     Scene scene = new Scene(grid); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

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

, 조금 까다이야가, 그러나 다음과 같은 작업을해야합니다 :

import java.util.ArrayList; 
import java.util.List; 

import javafx.beans.Observable; 
import javafx.beans.property.IntegerProperty; 
import javafx.beans.property.Property; 
import javafx.beans.property.SimpleIntegerProperty; 
import javafx.beans.value.ChangeListener; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.scene.Node ; 
import javafx.scene.control.Toggle; 

public class ToggleSet<T extends Node & Toggle> { 

    private final ObservableList<T> toggles = FXCollections.observableArrayList(t -> new Observable[] {t.selectedProperty()}); 
    private final ObservableList<T> selectedToggles = FXCollections.observableArrayList(); 
    private final IntegerProperty maximumSelectable = new SimpleIntegerProperty(0); 

    private final ChangeListener<Boolean> toggleListener = (obs, wasSelected, isNowSelected) -> { 
     @SuppressWarnings("unchecked") 
     T toggle = (T) ((Property<?>)obs).getBean(); 
     if (isNowSelected) { 
      selectedToggles.add(toggle); 
      ensureWithinMax(); 
     } else { 
      selectedToggles.remove(toggle); 
     } 
    }; 

    public ToggleSet(int maximumSelectable) { 

     this.maximumSelectable.addListener((obs, oldMax, newMax) -> ensureWithinMax()); 
     setMaximumSelectable(maximumSelectable); 
    } 

    private void ensureWithinMax() { 
     if (this.maximumSelectable.get() < selectedToggles.size()) { 
      List<Toggle> togglesToClear = new ArrayList<>(selectedToggles.subList(0, selectedToggles.size() - this.maximumSelectable.get())); 
      togglesToClear.forEach(t -> t.setSelected(false)); 
     } 
    } 

    public ToggleSet() { 
     this(0); 
    } 

    public ObservableList<T> getSelectedToggles() { 
     return FXCollections.unmodifiableObservableList(selectedToggles) ; 
    } 

    public IntegerProperty maximumSelectableProperty() { 
     return maximumSelectable ; 
    } 

    public final int getMaximumSelectable() { 
     return maximumSelectableProperty().get(); 
    } 

    public final void setMaximumSelectable(int maximumSelectable) { 
     maximumSelectableProperty().set(maximumSelectable); 
    } 

    public void addToggle(T toggle) { 
     if (toggle.isSelected()) { 
      selectedToggles.add(toggle); 
      ensureWithinMax(); 
     } 
     toggle.selectedProperty().addListener(toggleListener); 
     toggles.add(toggle); 
    } 

    public void removeToggle(T toggle) { 
     toggle.selectedProperty().removeListener(toggleListener); 
     toggles.remove(toggle); 
    } 

} 

(동일한 테스트 코드를 사용합니다.)

+0

와우 감사합니다. 그것은 정말 잘 작동하고 매끄럽게 느껴집니다. 나는 그것의 대부분을 사용할거야! –

관련 문제