gpt4 book ai didi

java - StyleableProperty : how to change value programatically at runtime?

转载 作者:行者123 更新时间:2023-11-28 11:21:04 26 4
gpt4 key购买 nike

我的用例:

  • 控件上的自定义属性,应该可以通过 css 配置
  • 该属性必须在运行时可以更改
  • 对于给定的控件实例,程序更改不得在重新应用 css 时恢复

自定义StyleableProperty看起来非常适合实现要求。下面是一个实现的例子(从 StyleablePropertyFactory 的类 javadoc 中获取而没有改变)。

除了最后一个要求外,一切都很好:在 applyCss 上,样式表中的默认值被重新应用。重现:

  • 运行示例,注意 MyButton 的初始“选中”状态(选中的复选框绑定(bind)它)为 true
  • 点击自定义按钮,注意“selected”不会变为 false(虽然 actionHandler 改变了它)
  • 点击第二个(“切换”)按钮,注意自定义按钮的选中状态变为false
  • 将鼠标悬停在自定义按钮上,注意选中状态回退为true

回落到 true 的原因(通过样式设置的值),可以追溯到状态变化时发生的 applyCss ...这是可以理解的,并且在大多数时候可能是正确的事情,但是不在我的上下文中。

所以问题:

  • 我使用 StyleableProperty 的方向正确吗?
  • 如果是这样,如何调整以使其在发生手动更改后不再重新应用?
  • 如果没有,还能做什么?
  • 或者可能会问完全错误的问题:也许可通过 css 设置的属性并不意味着(永久)由代码更改?

例子:

public class StyleableButtonDriver extends Application {

/**
* example code from class doc of StyleablePropertyFactory.
*/
private static class MyButton extends Button {

private static final StyleablePropertyFactory<MyButton> FACTORY
= new StyleablePropertyFactory<>(Button.getClassCssMetaData());

MyButton(String labelText) {
super(labelText);
getStyleClass().add("my-button");
setStyle("-my-selected: true");
}

// Typical JavaFX property implementation
public ObservableValue<Boolean> selectedProperty() { return (ObservableValue<Boolean>)selected; }
public final boolean isSelected() { return selected.getValue(); }
public final void setSelected(boolean isSelected) { selected.setValue(isSelected); }

// StyleableProperty implementation reduced to one line
private final StyleableProperty<Boolean> selected =
FACTORY.createStyleableBooleanProperty(
this, "selected", "-my-selected", s -> s.selected);

@Override
public List<CssMetaData<? extends Styleable, ?>> getControlCssMetaData() {
return FACTORY.getCssMetaData();
}

public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
return FACTORY.getCssMetaData();
}

}
private Parent createContent() {
MyButton button = new MyButton("styleable button");
button.setOnAction(e -> {
// does not work: reset on applyCss
boolean isSelected = button.isSelected();
button.setSelected(!isSelected);
});

CheckBox box = new CheckBox("button selected");
box.selectedProperty().bind(button.selectedProperty());

Button toggle = new Button("toggle button");
toggle.setOnAction(e -> {
boolean isSelected = button.isSelected();
button.setSelected(!isSelected);
});


BorderPane content = new BorderPane(button);
content.setBottom(new HBox(10, box, toggle));
return content;
}

@Override
public void start(Stage stage) throws Exception {
stage.setScene(new Scene(createContent(), 300, 200));
//same behavior as setting the style directly
// URL uri = getClass().getResource("xstyleable.css");
// stage.getScene().getStylesheets().add(uri.toExternalForm());
// not useful: would have to override all
// Application.setUserAgentStylesheet(uri.toExternalForm());
stage.setTitle(FXUtils.version());
stage.show();
}

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

@SuppressWarnings("unused")
private static final Logger LOG = Logger
.getLogger(StyleableButtonDriver.class.getName());

}

最佳答案

你在正确的轨道上,但由于你需要覆盖样式来源的默认优先级(用户代理样式表<以编程方式分配 Node.style属性),你不能使用 SyleablePropertyFactory 用于创建此属性。您需要创建一个 CssMetaData 对象,如果该属性是以编程方式分配的,则该对象将属性指示为不可设置。

private static class MyButton extends Button {

private static final List<CssMetaData<? extends Styleable, ?>> CLASS_CSS_METADATA;
private static final CssMetaData<MyButton, Boolean> SELECTED;

static {
SELECTED = new CssMetaData<MyButton, Boolean>("-my-selected", StyleConverter.getBooleanConverter()) {

@Override
public boolean isSettable(MyButton styleable) {
// not setable, if bound or set by user
return styleable.selected.getStyleOrigin() != StyleOrigin.USER && !styleable.selected.isBound();
}

@Override
public StyleableProperty<Boolean> getStyleableProperty(MyButton styleable) {
return styleable.selected;
}

};

// copy list of button css metadata to list and add new metadata object
List<CssMetaData<? extends Styleable, ?>> buttonData = Button.getClassCssMetaData();
List<CssMetaData<? extends Styleable, ?>> mybuttonData = new ArrayList<>(buttonData.size()+1);
mybuttonData.addAll(buttonData);
mybuttonData.add(SELECTED);
CLASS_CSS_METADATA = Collections.unmodifiableList(mybuttonData);
}

MyButton(String labelText) {
super(labelText);
getStyleClass().add("my-button");
setStyle("-my-selected: true");
}

// Typical JavaFX property implementation
public ObservableValue<Boolean> selectedProperty() { return selected; }
public final boolean isSelected() { return selected.get(); }
public final void setSelected(boolean isSelected) { selected.set(isSelected); }

// StyleableProperty implementation reduced to one line
private final SimpleStyleableBooleanProperty selected = new SimpleStyleableBooleanProperty(SELECTED, this, "selected");

@Override
public List<CssMetaData<? extends Styleable, ?>> getControlCssMetaData() {
return CLASS_CSS_METADATA;
}

public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
return CLASS_CSS_METADATA;
}

}

关于java - StyleableProperty : how to change value programatically at runtime?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54150807/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com