我希望在选择框中添加一个分隔符并仍然保持类型安全。
在我看过的所有例子中,他们只是做了以下事情:
ChoiceBox<Object> cb = new ChoiceBox<>();
cb.getItems().addAll("one", "two", new Separator(), "fadfadfasd", "afdafdsfas");
有没有人想出一个能够添加分隔符并仍能保持类型安全的解决方案?
我希望如果我想添加分隔符,我应该能够做到以下几点:
ChoiceBox<T> cb = new ChoiceBox<T>();
cb.getSeparators().add(1, new Separator()); // 1 is the index of where the separator should be
我不应该为了添加分隔符而牺牲类型安全性。
答案 0 :(得分:0)
你可以通过创建一个接口然后继承Separator来实现这个接口来解决它:
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Separator;
import javafx.scene.layout.GridPane;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class ChoiceBoxIsSafe extends Application {
interface FruitInterface { }
static public class Fruit implements FruitInterface {
private StringProperty name = new SimpleStringProperty();
Fruit(String name) {
this.name.set(name);
}
public StringProperty nameProperty() {
return name;
}
@Override
public String toString() {
return name.get();
}
}
static public class FruitySeparator extends Separator implements FruitInterface { }
@Override
public void start(Stage primaryStage) throws Exception {
GridPane grid = new GridPane();
grid.setHgap(10); grid.setVgap(10); grid.setPadding(new Insets(10));
ChoiceBox<FruitInterface> cb = new ChoiceBox<>();
cb.getItems().addAll(new Fruit("Apple"), new Fruit("Orange"), new FruitySeparator(), new Fruit("Peach"));
Text text = new Text("");
ReadOnlyObjectProperty<FruitInterface> selected = cb.getSelectionModel().selectedItemProperty();
text.textProperty().bind(Bindings.select(selected, "name"));
grid.add(cb, 0, 0);
grid.add(text, 1, 0);
Scene scene = new Scene(grid);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
但这不是一个优雅的&#34;解决方案并不是在所有情况下都可以完成(例如ChoiceBox<String>
)。
从ChoiceBox的实现来看,看起来好像是把分隔符当作ChoiceBox中的项目来处理: - (。
答案 1 :(得分:0)
如前所述,如果添加到项目(脏,脏),则仅支持分隔符。为了按照问题中预期的方式支持他们,我们需要:
虽然前者不是什么大问题,但后者需要完全重写(主要是c&amp; p)其皮肤,因为一切都隐藏在隐私中。如果重写已经发生了,那么它只是几行: - )
为了好玩,我正在尝试ChoiceBoxX来解决其选择处理中的一些令人讨厌的错误,所以无法抗拒尝试。
首先,添加对ChoiceBoxx本身的支持:
/**
* Adds a separator index to the list. The separator is inserted
* after the item with the same index. Client code
* must keep this list in sync with the data.
*
* @param separator
*/
public final void addSeparator(int separator) {
if (separatorsList.getValue() == null) {
separatorsList.setValue(FXCollections.observableArrayList());
}
separatorsList.getValue().add(separator);
};
然后在ChoiceBoxXSkin中进行了一些更改
最简单的是,监听器重新构建弹出窗口,menuItem将dataIndex存储在其属性中,并且需要通过其dataIndex访问弹出窗口的所有代码被委托给循环通过menuItems的方法,直到找到一个适合:
protected RadioMenuItem getMenuItemFor(int dataIndex) {
if (dataIndex < 0) return null;
int loopIndex = dataIndex;
while (loopIndex < popup.getItems().size()) {
MenuItem item = popup.getItems().get(loopIndex);
ObservableMap<Object, Object> properties = item.getProperties();
Object object = properties.get("data-index");
if ((object instanceof Integer) && dataIndex == (Integer) object) {
return item instanceof RadioMenuItem ? (RadioMenuItem)item : null;
}
loopIndex++;
}
return null;
}
答案 2 :(得分:0)
针对美国其他地区:
有一种使用代码执行此操作的更简单方法(也有使用FXML进行操作的简单方法,在代码中进行操作提供了更大的灵活性)。
您只需创建一个ObservableList,然后用您的项目(包括分隔符)填充它,然后将该列表分配给ChoiceBox,如下所示:
private void fillChoiceBox(ChoiceBox choiceBox) {
ObservableList items = FXCollections.observableArrayList();
items.add("one");
items.add("two");
items.add("three");
items.add(new Separator());
items.add("Apples");
items.add("Oranges");
items.add("Pears");
choiceBox.getItems().clear();
choiceBox.getItems().addAll(items);
}