使用CSS在JavaFX中设置RadioButton子元素的样式
我试图通过使用CSS来改变JavaFX中RadioButton的外观,但面临着这个问题。 根据JavaFX CSS参考指南,元素结构由子元素组成:使用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;
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