自定义组合框,JavaFX 中的居中文本
Custom combobox, centered text in JavaFX
我想将组合框按钮单元格中的文本居中对齐并使其成为默认行为。我已经知道如何在创建组合框对象时执行此操作。我如何在组合框的派生 class 中实现该方法?
box.setButtonCell(new ListCell<String>() {
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
setText(item);
setAlignment(Pos.CENTER_RIGHT);
Insets old = getPadding();
setPadding(new Insets(old.getTop(), 0, old.getBottom(), 0));
}
}
});
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListCell;
public class CustomComboBox<T> extends ComboBox<T> {
public CustomComboBox() {
super();
}
public CustomComboBox(ObservableList<T> items) {
super(items);
}
public BooleanProperty centeredProperty() { return centered; }
public final void setCentered(boolean value) { centeredProperty().set(value); }
public final boolean isCentered() { return centeredProperty().get(); }
private BooleanProperty centered = new SimpleBooleanProperty(this, "centered", false) {
private ListCell<T> originalBttonCell = getButtonCell();
@Override
protected void invalidated() {
if(get()) {
setButtonCell(new ListCell<T>() {
@Override
public void updateItem(T item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
setText(item.toString());
setAlignment(Pos.CENTER_RIGHT);
Insets old = getPadding();
setPadding(new Insets(old.getTop(), 0, old.getBottom(), 0));
}
}
});
}
else {
setButtonCell(originalBttonCell);
}
}
};
}
用法
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class CustomComboBoxTest extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
VBox p = new VBox();
CustomComboBox<String> box = new CustomComboBox<>(FXCollections.observableArrayList("Item 1", "Item 2", "Item 3"));
box.setValue("Item 2");
Button b = new Button("Change centered");
b.setOnAction( e -> {box.setCentered(!box.isCentered());});
p.getChildren().addAll(box, b);
Scene scene = new Scene(p);
primaryStage.setScene(scene);
primaryStage.setWidth(300);
primaryStage.setHeight(200);
primaryStage.show();
}
}
当然,您可以将代码(box
替换为 this
)移动到 class 的构造函数中(或将其放在初始化块中)。
但是为什么要创建一个子class,CSS 很容易让你做到这一点:
添加如下样式sheet到场景
.combo-box>.list-cell {
-fx-alignment: center;
}
如果您希望能够为单个 ComboBox
es 更改此行为,您只需添加一种方法来区分居中的 ComboBox
es 与其他 css 选择器,例如class
java代码
comboBox.getStyleClass().add("center-aligned");
CSS
.combo-box.center-aligned>.list-cell {
-fx-alignment: center;
}
使用伪class 可以让您更轻松地打开和关闭行为。以下代码中心在偶数索引处对齐每个项目:
@Override
public void start(Stage primaryStage) {
ComboBox<String> combo = new ComboBox<>();
PseudoClass centerAligned = PseudoClass.getPseudoClass("center-aligned");
combo.pseudoClassStateChanged(centerAligned, true);
combo.getSelectionModel().selectedIndexProperty().addListener((o, oldValue, newValue)
-> combo.pseudoClassStateChanged(centerAligned, newValue.intValue() % 2 == 0));
for (int i = 0; i < 5; i++) {
combo.getItems().add("item " + i);
}
combo.setValue("item 0");
combo.setMaxWidth(Double.MAX_VALUE);
VBox root = new VBox(combo);
root.setFillWidth(true);
root.setPrefWidth(300);
Scene scene = new Scene(root);
scene.getStylesheets().add("style.css");
primaryStage.setScene(scene);
primaryStage.show();
}
style.css
.combo-box:center-aligned>.list-cell {
-fx-alignment: center;
}
我想将组合框按钮单元格中的文本居中对齐并使其成为默认行为。我已经知道如何在创建组合框对象时执行此操作。我如何在组合框的派生 class 中实现该方法?
box.setButtonCell(new ListCell<String>() {
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
setText(item);
setAlignment(Pos.CENTER_RIGHT);
Insets old = getPadding();
setPadding(new Insets(old.getTop(), 0, old.getBottom(), 0));
}
}
});
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListCell;
public class CustomComboBox<T> extends ComboBox<T> {
public CustomComboBox() {
super();
}
public CustomComboBox(ObservableList<T> items) {
super(items);
}
public BooleanProperty centeredProperty() { return centered; }
public final void setCentered(boolean value) { centeredProperty().set(value); }
public final boolean isCentered() { return centeredProperty().get(); }
private BooleanProperty centered = new SimpleBooleanProperty(this, "centered", false) {
private ListCell<T> originalBttonCell = getButtonCell();
@Override
protected void invalidated() {
if(get()) {
setButtonCell(new ListCell<T>() {
@Override
public void updateItem(T item, boolean empty) {
super.updateItem(item, empty);
if (item != null) {
setText(item.toString());
setAlignment(Pos.CENTER_RIGHT);
Insets old = getPadding();
setPadding(new Insets(old.getTop(), 0, old.getBottom(), 0));
}
}
});
}
else {
setButtonCell(originalBttonCell);
}
}
};
}
用法
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class CustomComboBoxTest extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
VBox p = new VBox();
CustomComboBox<String> box = new CustomComboBox<>(FXCollections.observableArrayList("Item 1", "Item 2", "Item 3"));
box.setValue("Item 2");
Button b = new Button("Change centered");
b.setOnAction( e -> {box.setCentered(!box.isCentered());});
p.getChildren().addAll(box, b);
Scene scene = new Scene(p);
primaryStage.setScene(scene);
primaryStage.setWidth(300);
primaryStage.setHeight(200);
primaryStage.show();
}
}
当然,您可以将代码(box
替换为 this
)移动到 class 的构造函数中(或将其放在初始化块中)。
但是为什么要创建一个子class,CSS 很容易让你做到这一点:
添加如下样式sheet到场景
.combo-box>.list-cell {
-fx-alignment: center;
}
如果您希望能够为单个 ComboBox
es 更改此行为,您只需添加一种方法来区分居中的 ComboBox
es 与其他 css 选择器,例如class
java代码
comboBox.getStyleClass().add("center-aligned");
CSS
.combo-box.center-aligned>.list-cell {
-fx-alignment: center;
}
使用伪class 可以让您更轻松地打开和关闭行为。以下代码中心在偶数索引处对齐每个项目:
@Override
public void start(Stage primaryStage) {
ComboBox<String> combo = new ComboBox<>();
PseudoClass centerAligned = PseudoClass.getPseudoClass("center-aligned");
combo.pseudoClassStateChanged(centerAligned, true);
combo.getSelectionModel().selectedIndexProperty().addListener((o, oldValue, newValue)
-> combo.pseudoClassStateChanged(centerAligned, newValue.intValue() % 2 == 0));
for (int i = 0; i < 5; i++) {
combo.getItems().add("item " + i);
}
combo.setValue("item 0");
combo.setMaxWidth(Double.MAX_VALUE);
VBox root = new VBox(combo);
root.setFillWidth(true);
root.setPrefWidth(300);
Scene scene = new Scene(root);
scene.getStylesheets().add("style.css");
primaryStage.setScene(scene);
primaryStage.show();
}
style.css
.combo-box:center-aligned>.list-cell {
-fx-alignment: center;
}