Die Schaltflächen müssen sich im zweiten Bild in einem Raster befinden. Der erste Screenshot), bis einer von ihnen geklickt wird (siehe zweite Screenshot). Beachten Sie, dass eine Klick -Schaltfläche nur die Schaltflächen in ihrem Feld "fixieren". < /P>
Für den Kontext versuche ich, das Murdle des Spiels als Desktop -Anwendung neu zu erstellen, und ich muss sicherstellen, dass es auf anderen Bildschirmen als meinen eigenen funktioniert. StateButton ist im Wesentlichen nur eine Wrapper, um eine Taste mit einigen Spieldaten zu kombinieren. Ich kann das bei Bedarf hinzufügen
Ich habe versucht, die Vorabbreite der Schaltflächen an ihre Höhe zu binden. Ich habe auch versucht, die Zeilenbreiten der Raster -Schädigung zu ändern. All dies endet mit unerwartetem Verhalten, bei dem die Schaltflächen während der Größenänderung nicht als Netz bleiben. Mein Code folgt.
Code: Select all
private GridPane drawBlock(Block block) {
GridPane gridPane = new GridPane();
gridPane.getStyleClass().add("board-block");
DoubleProperty doubleProperty = new SimpleDoubleProperty();
for (int i = 0; i < block.getRowsList().size(); i++) {
for (int j = 0; j < block.getRowsList().get(i).getBoxes().size(); j++) {
StateButton stateButton = new StateButton();
stateButton.setBox(block.getRowsList().get(i).getBoxes().get(j));
stateButton.setOnAction(e -> stateButton.updateState());
stateButton.textProperty().bind(stateButton.getBox().stateIconProperty());
// stateButton.maxHeightProperty().bind(stateButton.widthProperty());
stateButton.prefHeightProperty().bind(stateButton.widthProperty());
// stateButton.minHeightProperty().bind(stateButton.widthProperty());
stateButton.getBox().setState(Box.BoxState.UNSURE);
stateButton.getBox().update();
if (i+j==0) doubleProperty.bind(stateButton.widthProperty());
}
}
RowConstraints rowConstraints = new RowConstraints();
rowConstraints.prefHeightProperty().bind(doubleProperty);
gridPane.getRowConstraints().add(rowConstraints);
return gridPane;
}
< /code>
StateButton Code < /p>
@Setter
@Getter
public class StateButton extends Button {
private Box box;
public void updateState() {
box.update();
}
public StateButton() {
super();
getStyleClass().add("state-button");
}
}
< /code>
Boxklassencode < /p>
@AllArgsConstructor
public class Box {
@Getter
private BoxState state;
private StringProperty stateIcon;
private List eliminationListeners = new ArrayList();
public Box() {
state = BoxState.UNMARKED;
stateIcon = new SimpleStringProperty(state.getIcon());
}
public Box(BoxState newState) {
this.state = newState;
this.stateIcon = new SimpleStringProperty(newState.getIcon());
}
public void setState(BoxState state){
this.state = state;
stateIcon.setValue(state.getIcon());
}
public void addEliminationListener(EliminationListener listener) {
eliminationListeners.add(listener);
}
public StringProperty stateIconProperty() { return stateIcon; }
public final String getSateIcon() { return stateIcon.getValue(); }
public final void setStateIcon(String icon) {
stateIcon.setValue(icon);
}
public void populateFromBox(Box box) {
this.setState(box.getState());
}
public Box clone() {
return new Box(state);
}
public void update() {
state = state.update(eliminationListeners);
switch (state) {
case TRUE -> eliminationListeners.forEach(EliminationListener::eliminate);
case UNSURE -> eliminationListeners.forEach(EliminationListener::uneliminate);
}
setStateIcon(state.getIcon());
}
public void eliminate() {
state = state.onEliminated();
stateIcon.setValue(state.getIcon());
}
public void uneliminate() {
state = state.onUneliminated(eliminationListeners);
stateIcon.setValue(state.getIcon());
}
public enum BoxState {
UNMARKED{
@Override
public BoxState update(List eliminationListeners) {
return BoxState.FALSE;
}
@Override
public BoxState onEliminated() {
return BoxState.FALSE_BY_ELIMINATION;
}
@Override
public String getIcon() { return ""; }
},
FALSE {
@Override
public BoxState update(List eliminationListeners) {
return checkEliminable(eliminationListeners) ? BoxState.FALSE : BoxState.TRUE;
}
@Override
public String getIcon() { return "❌";}
},
TRUE {
@Override
public BoxState update(List eliminationListeners) {
return BoxState.UNSURE;
}
@Override
public String getIcon() { return "✅"; }
},
UNSURE {
@Override
public BoxState update(List eliminationListeners) {
return checkEliminable(eliminationListeners) ? BoxState.FALSE_BY_ELIMINATION : BoxState.UNMARKED; //good
}
@Override
public String getIcon() { return "❓"; }
},
FALSE_BY_ELIMINATION {
@Override
public BoxState onUneliminated(List eliminationListeners) {
return !checkEliminable(eliminationListeners) ? BoxState.UNMARKED : BoxState.FALSE_BY_ELIMINATION;
}
@Override
public String getIcon() { return "ⅹ"; }
};
public BoxState update(List eliminationListeners) {
return this;
}
public BoxState onEliminated() {
return this;
}
public BoxState onUneliminated(List eliminationListeners) {
return this;
}
public abstract String getIcon();
private static boolean checkEliminable(List eliminationListeners) {
return eliminationListeners.stream().anyMatch(EliminationListener::checkEliminable);
}
}
}
< /code>
Blockklasse < /p>
@Data
@AllArgsConstructor
public class Block {
private List rowsList;
private List columnsList;
private SuspectType rowType;
private SuspectType columnType;
public Block(List