如何用另一个组合框的选择填充组合框? JavaFX

时间:2019-06-05 05:39:07

标签: java javafx arraylist combobox

我已经开始为March Madness bracket生成器创建GUI,将回合1的所有64个团队显示为Labels,现在我正尝试为每个比赛创建一个ComboBox下拉菜单

我已经为2场比赛创建了一个ComboBox,现在我想创建一个新的ComboBox,将其选项从其他两个ComboBox中拉出来。因此,在下面的示例图中,新的ComboBox应该具有选项Duke和VCU,供用户选择。

           (2 combo boxes)        (new combo box)

Duke------
               Duke ---   
ND St. ---

                                        X

VCU -----
               VCU ---
UCF -----  

我该怎么做?

public class ControlPanel extends Application
{

    @Override
    public void start(Stage primaryStage) {

        primaryStage.setTitle("March Madness 2019 Generator");

        BorderPane componentLayout = new BorderPane();
        componentLayout.setPadding(new Insets(20,0,20,20));

        final FlowPane choicePane = new FlowPane();
        choicePane.setHgap(100);
        Label choiceLbl = new Label("Match1");

        ArrayList<Team> round1 = new ArrayList<Team>();

        round1.add(new Team("Duke", 0.670, 1));                    //0
        round1.add(new Team("North Dakota St", 0.495, 16));
        round1.add(new Team("VCU", 0.609, 8));
        round1.add(new Team("UCF", 0.606, 9));


        //The choicebox is populated from an observableArrayList
        ChoiceBox r2Match1 = new ChoiceBox(FXCollections.observableArrayList(  match(round1, 0, 1)   ));

        //Add the label and choicebox to the flowpane
        choicePane.getChildren().add(choiceLbl);
        choicePane.getChildren().add(r2Match1);

        //put the flowpane in the top area of the BorderPane
        componentLayout.setTop(choicePane);

        //Add the BorderPane to the Scene
        Scene appScene = new Scene(componentLayout,500,500);
        //Add the Scene to the Stage
        primaryStage.setScene(appScene);
        primaryStage.show();
    }

    private ArrayList<Team> match(ArrayList<Team> roundPullFrom, int team1, int team2) {
        ArrayList<Team> temp = new ArrayList<Team>();
        temp.add(roundPullFrom.get(team1));
        temp.add(roundPullFrom.get(team2));
        return temp;
    }

}

2 个答案:

答案 0 :(得分:0)

问题的结构是一棵树。因此,您可能希望解决方案支持该结构。您可以使用Binary Tree data structure类似于比赛,也可以通过以下方式创建这样的结构:拥有类似的课程:

class Team {
   String name;
}

class Match {
   Team teamA;
   Team teamB;
   String where;
   Date when;

   public Team selectWinner() { 
     ...
   }
}

class Tournament {
   List<Team> teams;
   List<Match> getMatches(int round,List<Team> teams) {
     List<Match> matches=new ArrayList<Match>)();
     if (round==1) {
       for (teamIndex=1;teamIndex<=teams.size();teamIndex+=2) {
         Match match=new Match(teams[teamIndex-1],teams(teamIndex)];
         matches.add(match);
       }
     } else { 
       List<Team> winners=new ArrayList<Team>();
       for (Match match:getMatches(round-1)) {
         winners.add(match.selectWinner());
       }
       return getMatches(1,winners);
     }
   }
}

然后,从该结构中,您可以派生出必要的gui组件,以使选择动态化,并使GUI组件从Tournament,Match和Team类中获取其值。

答案 1 :(得分:0)

使用在我的previous answer中发布的方法将ComboBox成对组合,直到剩下一个ComboBox

以下代码也将节点布局为类似于树结构的布局,但是您可以通过将每一轮都保留在数据结构中而不是覆盖单个数组的值来轻松地使布局分离。 (由于要访问数据,因此无论如何都应将组合存储在适当的数据结构中。)

private static ComboBox<String> createCombo(double x, double y, double width) {
    ComboBox<String> comboBox = new ComboBox<>();
    comboBox.setLayoutX(x);
    comboBox.setLayoutY(y);
    comboBox.setMaxWidth(Region.USE_PREF_SIZE);
    comboBox.setMinWidth(Region.USE_PREF_SIZE);
    comboBox.setPrefWidth(width);

    return comboBox;
}

private static Label createLabel(String text, double maxWidth) {
    Label label = new Label(text);
    label.setMaxWidth(maxWidth);
    return label;
}

@Override
public void start(Stage primaryStage) {
    String[] teams = new String[64];
    for (int i = 0; i < teams.length; i++) {
        teams[i] = Integer.toString(i);
    }
    final double offsetY = 30;
    final double offsetX = 100;
    final double width = 90;

    Pane root = new Pane();

    // array storing the comboboxes
    // combos for previous round are at the lowest indices
    ComboBox<String>[] combos = new ComboBox[teams.length / 2];

    // create initial team labels & comboboxes
    for (int i = 0, offsetTeams = 0; i < combos.length; i++, offsetTeams += 2) {
        Label label = createLabel(teams[offsetTeams], width);
        double y = offsetTeams * offsetY;
        label.setLayoutY(y);
        root.getChildren().add(label);

        label = createLabel(teams[offsetTeams+1], width);
        label.setLayoutY(y+offsetY);

        ComboBox<String> comboBox = createCombo(offsetX, y + offsetY / 2, width);
        comboBox.getItems().addAll(teams[offsetTeams], teams[offsetTeams+1]);
        combos[i] = comboBox;

        root.getChildren().addAll(label, comboBox);
    }

    double x = 2 * offsetX;
    int count = combos.length / 2; // combos still left for the next round

    for (; count > 0; count /= 2, x += offsetX) { // for each round
        // create comboboxes combining the combos from previous round pairwise
        for (int i = 0, ci = 0; i < count; i++, ci+=2) {
            // get combos pairwise
            ComboBox<String> c1 = combos[ci];
            ComboBox<String> c2 = combos[ci+1];

            ComboBox<String> combo = createCombo(x, (c1.getLayoutY() + c2.getLayoutY()) / 2, width) ;

            // combine data from previous round
            ChangeListener<String> listener = (o, oldValue, newValue) -> {
                final List<String> items = combo.getItems();
                int index = items.indexOf(oldValue);
                if (index >= 0) {
                    if (newValue == null) {
                        items.remove(index);
                    } else {
                        items.set(index, newValue);
                    }
                } else if (newValue != null) {
                    items.add(newValue);
                }
            };
            c1.valueProperty().addListener(listener);
            c2.valueProperty().addListener(listener);

            root.getChildren().add(combo);
            combos[i] = combo;
        }
    }

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