使用CSS在JavaFX中设置RadioButton子元素的样式

使用CSS在JavaFX中设置RadioButton子元素的样式,java,css,javafx,javafx-8,Java,Css,Javafx,Javafx 8,我试图通过使用CSS来改变JavaFX中RadioButton的外观,但面临着这个问题。 根据JavaFX CSS参考指南,元素结构由子元素组成: radio — Region dot — Region label — Label modena.css中风格化的子元素无线电: .radio-button > .radio, .radio-button:focused > .radio { -fx-background-radius: 1.0em;

我试图通过使用CSS来改变JavaFX中RadioButton的外观,但面临着这个问题。 根据JavaFX CSS参考指南,元素结构由子元素组成:

   radio — Region
      dot — Region
   label — Label
modena.css中风格化的子元素无线电:

.radio-button > .radio,
.radio-button:focused > .radio  {
   -fx-background-radius: 1.0em;
   -fx-padding: 0.333333em;
}
通过重写这些样式类,可以配置子元素的外观。 Sub.dot也有样式化。 但是如果我尝试向子元素标签添加代码,例如:

.radio-button > .label,
.radio-button:focused > .label {
   -fx-background-color: rgb(200,200,200);
}
……什么也没发生。 如何将此sub样式化?
有没有一种方法可以查看元素的内部结构和css属性,您可以更改这些元素(JavaFX css参考指南除外)?

您不需要显式设置标签的样式

如果要更改标签的颜色,可以非常轻松地执行以下操作:

.radio-button {
    -fx-text-fill: yourColor;
}

您不需要显式设置标签的样式

如果要更改标签的颜色,可以非常轻松地执行以下操作:

.radio-button {
    -fx-text-fill: yourColor;
}

您尝试样式化的子元素实际上是一个扩展javafx.scene.text.text的LabeledText对象。从中可以看出,它有自己的属性,再加上字体和形状属性。这些属性都不允许您自定义“标签”区域,只允许自定义文本


我的建议是使用没有文本的单选按钮,并放置一个“标签”“除此之外,还可以使用其他可以自定义的组件。

您尝试样式化的子元素实际上是一个扩展javafx.scene.text.text的LabeledText对象。从中可以看出,它有自己的属性,再加上字体和形状属性。这些属性都不允许您自定义“标签”区域,只允许自定义文本


我的建议是使用一个没有文本的单选按钮,并使用其他可以自定义的组件在其旁边放置一个“标签”。

问题的第二部分我将自己回答。为了显示元素JavaFX的结构和属性,我编写了该实用程序。也许有人会发现它很有用

public class CssMetaDataExtractor extends Application {
private Stage primaryStageLink;
private Scene primaryScene;
private SplitPane rootNode;
private Group group;
private TreeView<String> structureTV;
private Component structureRoot;
private TreeView<String> nodePropertiesTV;
private TreeItem<String> nodePropertiesRoot;
private TreeTableView<CMDComponent> cssPropertiesTV;
private TreeItem<CMDComponent> cssPropertiesRoot;

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

@Override
public void start(Stage primaryStage) {
    primaryStageLink = primaryStage;
    createContent();
    primaryScene.getStylesheets().add( CssMetaDataExtractor.class.getResource("test.css").toExternalForm() );
    /* Create and tune your element here... */
    ProgressBar pb = new ProgressBar();
    /* ...and add element here... */
    processElement( pb );
}

private void processElement(Node node) {
    group.getChildren().add(node);
    primaryStageLink.show();
    if ( node instanceof Parent ) {
        extractCssMetaData((Parent)node, null);
        node.addEventHandler(Event.ANY, (Event event) -> {
            Component selected = (Component)structureTV.getSelectionModel().selectedItemProperty().getValue();
            showCssProperties( selected );
            showNodeProperties( selected );
        });
    }
}
private void extractCssMetaData(Parent node, Component parent) {
    Component currentParent = parent;
    if (parent == null) {
        structureRoot = new Component( node );
        currentParent = structureRoot;
        primaryStageLink.setTitle("CssMetaDataExtractor for [" + node.getClass().getName() + "]");
    }
    for (Node subNode : node.getChildrenUnmodifiable()) {
        Component child = new Component( subNode );
        currentParent.getChildren().add( child );
        if (subNode instanceof Parent) {                
            extractCssMetaData((Parent)subNode, child);
        }
    }
    structureRoot.setExpanded(true);
    structureTV.setRoot(structureRoot);
    if ( structureTV.getSelectionModel().getSelectedItems().size() == 0 ) {
        structureTV.getSelectionModel().selectFirst();
    }
}
private void showNodeProperties(Component component) {
    nodePropertiesRoot = new TreeItem( component.getNode().getClass().getName() );
    TreeItem<String> selector = new TreeItem("Selector");
    selector.setExpanded(true);
    selector.getChildren().add( new TreeItem( getSelectorHierarchy(component) ) );
    nodePropertiesRoot.getChildren().add( selector );
    if ( component.getNode().getPseudoClassStates() != null && component.getNode().getPseudoClassStates().size() > 0 ) {
        TreeItem<String> pseudoClasses = new TreeItem("PseudoClass States");
        pseudoClasses.setExpanded(true);
        for ( PseudoClass pc : component.getNode().getPseudoClassStates() ) {
            pseudoClasses.getChildren().add( new TreeItem( pc.getPseudoClassName() + " [" + pc.getClass().getName() + "]" ) );
        }
        nodePropertiesRoot.getChildren().add( pseudoClasses );
    }
    if ( component.getNode().getStyle() != null && component.getNode().getStyle().length() > 0 ) {
        TreeItem<String> style = new TreeItem("Style");
        style.setExpanded(true);
        style.getChildren().add( new TreeItem( component.getNode().getStyle() ) );
        nodePropertiesRoot.getChildren().add( style );
    }
    if ( component.getNode().getTypeSelector() != null & component.getNode().getTypeSelector().length() > 0 ) {
        TreeItem<String> typeSelector = new TreeItem("Type Selector");
        typeSelector.setExpanded(true);
        typeSelector.getChildren().add( new TreeItem( component.getNode().getTypeSelector() ) );
        nodePropertiesRoot.getChildren().add( typeSelector );
    }
    if ( component.getNode().getId() != null && component.getNode().getId().length() > 0 ) {
        TreeItem<String> id = new TreeItem("Id");
        id.setExpanded(true);
        id.getChildren().add( new TreeItem( component.getNode().getId() ) );
        nodePropertiesRoot.getChildren().add( id );
    }
    if ( component.getNode().getProperties() != null && component.getNode().getProperties().size() > 0 ) {
        TreeItem<String> properties = new TreeItem("Properties");
        properties.setExpanded(true);
        for ( Object key : component.getNode().getProperties().keySet() ) {
            properties.getChildren().add( new TreeItem( key + "=" + component.getNode().getProperties().get(key) ) );
        }
        nodePropertiesRoot.getChildren().add( properties );
    }
    if ( component.getNode().getAccessibleRole() != null ) {
        TreeItem<String> accessibleRole = new TreeItem("Accessible Role");
        accessibleRole.setExpanded(true);
        accessibleRole.getChildren().add( new TreeItem( component.getNode().getAccessibleRole() ) );
        nodePropertiesRoot.getChildren().add( accessibleRole );
        if ( component.getNode().getAccessibleRoleDescription() != null && component.getNode().getAccessibleRoleDescription().length() > 0 ) {
            accessibleRole.getChildren().add( new TreeItem( component.getNode().getAccessibleRoleDescription() ) );
        }
    }
    if ( component.getNode().getAccessibleText() != null && component.getNode().getAccessibleText().length() > 0 ) {
        TreeItem<String> accessibleText = new TreeItem("Accessible Text");
        accessibleText.setExpanded(true);
        accessibleText.getChildren().add( new TreeItem( component.getNode().getAccessibleText() ) );
        nodePropertiesRoot.getChildren().add( accessibleText );
    }
    nodePropertiesRoot.setExpanded(true);
    nodePropertiesTV.setRoot(nodePropertiesRoot);
    nodePropertiesTV.setShowRoot(false);
}
private String getSelectorHierarchy(Component component) {
    Component current = component;
    StringBuilder selectors = new StringBuilder();
    while (true) {
        StringBuilder sb = new StringBuilder();
        if ( current.getNode().getStyleClass().size() > 1 ) {
            sb.append("[ ");
            for ( String styleClass : current.getNode().getStyleClass() ) {
                sb.append(".").append(styleClass).append(" | ");
            }
            sb.delete(sb.length()-3, sb.length());
            sb.append(" ]");
        } else if ( current.getNode().getStyleClass().size() == 1 ) {
            sb.append(".").append( current.getNode().getStyleClass() );
        } else {
            sb.append("NULL");
        }
        if ( current.getParent() != null ) {
            sb.insert(0, " > ");
            selectors.insert(0, sb);
            current = (Component)current.getParent();
        } else {
            selectors.insert(0, sb);
            break;
        }
    }
    return selectors.toString();
}
private void showCssProperties(Component component) {
    if ( component.getNode().getCssMetaData() != null && component.getNode().getCssMetaData().size() > 0 ) {
        cssPropertiesRoot = new TreeItem<CMDComponent>( new CMDComponent() );
        for ( CssMetaData cmd : component.getNode().getCssMetaData() ) {
            addProperty(cmd, component.getNode(), cssPropertiesRoot);
        }
        cssPropertiesRoot.setExpanded(true);
        cssPropertiesTV.setRoot(cssPropertiesRoot);
        cssPropertiesTV.setShowRoot(false);
    }
}    
private void addProperty(CssMetaData cmd, Node node, TreeItem<CMDComponent> parent) {
    TreeItem<CMDComponent> child = new TreeItem<CMDComponent>( new CMDComponent(cmd, node) );
    parent.getChildren().add( child );
    if ( cmd.getSubProperties() != null ) {
        for ( Object subcmd : cmd.getSubProperties() ) {
            if ( subcmd instanceof CssMetaData ) {
                addProperty( (CssMetaData)subcmd, node, child );
            }
        }
    }
}
private class Component extends TreeItem<String> {
    private Node node;
    public Component(Node node) {
        super(node.getClass().getName());
        this.node = node;
    }
    public Node getNode() { return node; }
    public void setNode(Node node) { this.node = node; }
}
private class CMDComponent {
    private SimpleStringProperty name = new SimpleStringProperty();
    private SimpleStringProperty converterName = new SimpleStringProperty();
    private SimpleStringProperty initialValue = new SimpleStringProperty();
    private SimpleStringProperty styledValue = new SimpleStringProperty();
    private Node node;
    public CMDComponent() {
        this.name.set("none");
        this.converterName.set("none");
        this.initialValue.set("none");
        this.styledValue.set("none");
    }
    public CMDComponent(CssMetaData cssMetaData, Node node) {
        this.name.set(cssMetaData.getProperty());
        this.converterName.set(cssMetaData.getConverter().toString());
        if ( cssMetaData.getInitialValue(node) != null ) {
            this.initialValue.set(cssMetaData.getInitialValue(node).toString());
        } else {
            this.initialValue.set("null");
        }
        if ( cssMetaData.getStyleableProperty(node) != null ) {
            if ( cssMetaData.getStyleableProperty(node).getValue() != null ) {
                this.styledValue.set( cssMetaData.getStyleableProperty(node).getValue().toString() );
            } else {
                this.styledValue.set("null");
            }
        } else {
            this.styledValue.set("null");
        }
        this.node = node;
    }
    public String getName() { return name.get(); }
    public void setName(String name) { this.name.set(name); }
    public String getConverterName() { return converterName.get(); }
    public void setConverterName(String converterName) { this.converterName.set(converterName); }
    public String getInitialValue() { return initialValue.get(); }
    public void setInitialValue(String initialValue) { this.initialValue.set(initialValue); }
    public String getStyledValue() { return styledValue.get(); }
    public void setStyledValue(String styledValue) { this.styledValue.set(styledValue); }
}
private void createContent() {
    rootNode = new SplitPane();
    rootNode.setOrientation(Orientation.HORIZONTAL);
    rootNode.setDividerPosition(0, 0.25);
    primaryScene = new Scene(rootNode, 1300, 900);
    primaryStageLink.setScene(primaryScene);
    primaryStageLink.initStyle(StageStyle.DECORATED);
    SplitPane splitPane = new SplitPane();
    splitPane.setOrientation(Orientation.VERTICAL);
    splitPane.setDividerPosition(0, 0.15);
    splitPane.setDividerPosition(1, 0.6);
    rootNode.getItems().add(splitPane);
    ScrollPane scrollPane = new ScrollPane();
    group = new Group();
    scrollPane.setContent(group);
    splitPane.getItems().add(scrollPane);
    structureTV = new TreeView<>();
    structureTV.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
    structureTV.getSelectionModel().selectedItemProperty().addListener(
        (ObservableValue<? extends TreeItem<String>> observable, TreeItem<String> oldValue, TreeItem<String> newValue) -> {
            showCssProperties( (Component)newValue );
            showNodeProperties( (Component)newValue );
        }
    );
    splitPane.getItems().add(structureTV);
    nodePropertiesTV = new TreeView<>();
    splitPane.getItems().add(nodePropertiesTV);
    cssPropertiesTV = new TreeTableView();
    TreeTableColumn<CMDComponent, String> nameColumn = new TreeTableColumn<>("Name");
    nameColumn.setPrefWidth(250);
    nameColumn.setCellValueFactory(
        (TreeTableColumn.CellDataFeatures<CMDComponent, String> param) ->
            new ReadOnlyStringWrapper(param.getValue().getValue().getName())
    );
    TreeTableColumn<CMDComponent, String> initialColumn = new TreeTableColumn<>("Initial Value");
    initialColumn.setPrefWidth(275);
    initialColumn.setCellValueFactory(
        (TreeTableColumn.CellDataFeatures<CMDComponent, String> param) ->
            new ReadOnlyStringWrapper(param.getValue().getValue().getInitialValue() )
    );
    TreeTableColumn<CMDComponent, String> styledColumn = new TreeTableColumn<>("Styled Value");
    styledColumn.setPrefWidth(275);
    styledColumn.setCellValueFactory(
        (TreeTableColumn.CellDataFeatures<CMDComponent, String> param) ->
            new ReadOnlyStringWrapper(param.getValue().getValue().getStyledValue() )
    );
    TreeTableColumn<CMDComponent, String> converterColumn = new TreeTableColumn<>("Default Converter");
    converterColumn.setPrefWidth(170);
    converterColumn.setCellValueFactory(
        (TreeTableColumn.CellDataFeatures<CMDComponent, String> param) ->
            new ReadOnlyStringWrapper(param.getValue().getValue().getConverterName() )
    );
    cssPropertiesTV.getColumns().setAll(nameColumn, initialColumn, styledColumn, converterColumn);
    rootNode.getItems().add(cssPropertiesTV);
}}
公共类CSSMetataExtractor扩展应用程序{
私人舞台初级舞台;
私密场景主要场景;
私有SplitPane根节点;
私人集团;
私有TreeView结构电视;
私有组件结构根;
私有树视图节点属性TV;
私有树项nodeProperties根;
私有树视图cssPropertiesTV;
私有树项目cssPropertiesRoot;
公共静态void main(字符串[]args){
发射(args);
}
@凌驾
公共无效开始(阶段primaryStage){
primaryStageLink=初级阶段;
createContent();
添加(CssMetaDataExtractor.class.getResource(“test.css”).toExternalForm());
/*在这里创建并调整您的元素*/
ProgressBar pb=新的ProgressBar();
/*…并在此处添加元素*/
过程元素(pb);
}
私有void processElement(节点){
group.getChildren().add(节点);
primaryStageLink.show();
if(父节点的节点实例){
extractCssMetaData((父)节点,null);
node.addEventHandler(Event.ANY,(Event-Event)->{
所选组件=(组件)结构tv.getSelectionModel().selectedItemProperty().getValue();
showCssProperties(选定);
showNodeProperties(选定);
});
}
}
私有void extractCssMetaData(父节点、组件父节点){
组件currentParent=父级;
如果(父项==null){
structureRoot=新组件(节点);
currentParent=structureRoot;
setTitle(“cssmetataextractor for[”+节点.getClass().getName()+“]);
}
对于(节点子节点:Node.getChildrenUnmodifiable()){
组件子节点=新组件(子节点);
currentParent.getChildren().add(子级);
if(父节点的子节点实例){
extractCssMetaData((父)子节点,子节点);
}
}
structureRoot.setExpanded(true);
structureTV.setRoot(structureRoot);
如果(structureTV.getSelectionModel().getSelectedItems().size()==0){
structureTV.getSelectionModel().selectFirst();
}
}
私有void showNodeProperties(组件){
nodePropertiesRoot=新树项(component.getNode().getClass().getName());
TreeItem选择器=新的TreeItem(“选择器”);
selector.setExpanded(true);
selector.getChildren().add(新树项(getSelectorHierarchy(component));
nodePropertiesRoot.getChildren().add(选择器);
if(component.getNode().getPseudoClassState()!=null&&component.getNode().getPseudoClassState().size()>0){
TreeItem伪类=新的TreeItem(“伪类状态”);
伪类。setExpanded(true);
对于(伪类pc:component.getNode().getPseudoClassState()){
pseudoClasses.getChildren().add(新树项(pc.getPseudoClassName()+“[”+pc.getClass().getName()+“]));
}
nodePropertiesRoot.getChildren().add(伪类);
}
if(component.getNode().getStyle()!=null&&component.getNode().getStyle().length()>0){
TreeItem样式=新的TreeItem(“样式”);
style.setExpanded(true);
style.getChildren().add(新的TreeItem(component.getNode().getStyle());
nodePropertiesRoot.getChildren().add(样式);
}
if(component.getNode().getTypeSelector()!=null&component.getNode().getTypeSelector().length()>0){
TreeItem类型选择器=新的TreeItem(“类型选择器”);
typeSelector.setExpanded(true);
typeSelector.getChildren().add(新树项(component.getNode().getTypeSelector());
nodePropertiesRoot.getChildren().add(类型选择器);
}
if(component.getNode().getId()!=null&&component.getNode().getId().length()>0){
TreeItem id=新的TreeItem(“id”);
id.setExpanded(true);
id.getChildren().add(新的TreeItem(component.getNode().getId());
nodePropertiesRoot.getChildren().add(id);
}
if(component.getNode().getProperties()!=null&&component.getNode().getP