有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何通过JavaFX而不是FXML CSS修改菜单按钮箭头颜色?

我试图修改MenuButton箭头的颜色,使用的是JavaFX代码,而不是CSS

我在caspian.css里面找到了它:

.menu-button > .arrow-button > .arrow {
    -fx-background-insets: 1 0 -1 0, 0;
    -fx-background-color: -fx-mark-highlight-color, -fx-mark-color;
    -fx-padding: 0.25em; /* 3 */
    -fx-shape: "M 0 -3.5 v 7 l 4 -3.5 z";
}

我试着用这样的方法:

menubutton.lookup(".arrow");

但是它抛出NullPointerException

当我这么做的时候:

System.out.println(this.getStyleClass().toString());

它只指出:menu-button

那么,有谁能给我一个不用CSS而用Java修改它的方法吗


共 (2) 个答案

  1. # 1 楼答案

    有几种方法可以做到这一点,这里有四种。代码是Jython和JavaFX。您可以编辑此代码以满足您的需要


    First, the enum, for context.

    public enum URLBarArrowConstants {
         //URLBarArrow Constants
         BYCSS_AND_SHAPE,
         BYCSS_AND_NO_SHAPE,
         NOCSS_AND_SHAPE,
         NOCSS_AND_NO_SHAPE;
    }
    

    Second, the css files, for context.

    例1

    /*ComboBox's Arrow is a Region.*/
    .combo-box .arrow-button .arrow {
         -fx-shape: "...";
         -fx-scale-shape: true;
         -fx-position-shape: true;
    }
    

    例2

    /*ComboBox's Arrow is a Region.*/
    .combo-box .arrow-button .arrow {
        /*Setting either of these two will do.*/
         -fx-background-color: transparent; 
         -fx-opacity: 0.0;  
    }
    
    /*ComboBox's Arrow Button is a Stack Pane.*/
    .combo-box .arrow-button{
        -fx-background-position: center;
        -fx-background-repeat: no-repeat;
        -fx-background-image: url("..<file>.png");
    }
    

    The method, in my main file.

    def setCustomURLBarArrow(self, url_bar, scene, URLBarArrowConstant):
        from javafx.scene.paint import Paint
        from javafx.scene.shape import Shape, SVGPath, FillRule
    

    不要通过CSS配置组合框箭头,而是通过编程方式进行配置,并更改SVG形状

    if URLBarArrowConstant == URLBarArrowConstants.NOCSS_AND_SHAPE:
    
        #SVG Object
        previous_url_bar = SVGPath()
    
        #SVG Path
        previous_url_bar.setContent("...") # edit this 
    
        #SVG Fill Rule
        previous_url_bar.setFillRule(FillRule.NON_ZERO)
    
        #Set Fill   
        previous_url_bar.setFill(Paint.valueOf(Color.web("...").toString())) //edit here
    
        #Apply CSS Sheet
        url_bar.applyCss()
    
        #Set Region's Shape
        arrow_region = url_bar.lookup(".arrow").setShape(previous_url_bar)
    

    通过CSS配置组合框箭头并更改SVG形状

    elif URLBarArrowConstant == URLBarArrowConstants.BYCSS_AND_SHAPE:
        #Apply Stylesheet for URL Bar
        scene.getStylesheets().add(File("..<file>.css").toURI().toString()) //edit here
    

    通过CSS配置组合框箭头,但只需通过设置透明度/不透明度值和设置背景来隐藏箭头

    elif URLBarArrowConstant == URLBarArrowConstants.BYCSS_AND_NO_SHAPE:
        #Apply Stylesheet for URL Bar
        scene.getStylesheets().add(File("..<file>.css").toURI().toString()) //edit here
    

    不要通过CSS配置组合框箭头,而是通过编程实现,只需通过设置透明度/不透明度值和设置背景来隐藏箭头

    elif URLBarArrowConstant == URLBarArrowConstants.NOCSS_AND_NO_SHAPE:
    
        from javafx.scene.paint import Paint
        from javafx.scene.layout import CornerRadii
        from javafx.scene.layout import Background, BackgroundSize, BackgroundImage, BackgroundPosition, BackgroundRepeat, BackgroundFill
    
        #Apply CSS Sheet
        url_bar.applyCss()
    
        #Grab Arrow(Region), ArrowButton(StackPane) ComboBox properties
        arrow_region = url_bar.lookup(".arrow")
        arrow_button = url_bar.lookup(".arrow-button")
    
        #Either Set Opacity to 0 or set background color to transparent.
        arrow_region.setOpacity(0.0)
        arrow_region.setBackground( Background( array(BackgroundFill, [BackgroundFill( Paint.valueOf(Color.TRANSPARENT.toString()), CornerRadii.EMPTY, Insets.EMPTY)]) ) )
    
        #Set a Background Image for the .arrow-button StackPane.
        arrow_button.setBackground(Background( array(BackgroundImage, [BackgroundImage( Image( String(File('..<file>.png').toURI().toString()), True) , BackgroundRepeat.NO_REPEAT, BackgroundRepeat.NO_REPEAT, BackgroundPosition.CENTER, BackgroundSize.DEFAULT)] ) ) )       //if you want, edit this
    
  2. # 2 楼答案

    这是有效的:

    import javafx.application.Application;
    import javafx.scene.Scene;
    import javafx.scene.control.MenuButton;
    import javafx.scene.control.MenuItem;
    import javafx.scene.layout.StackPane;
    import javafx.stage.Stage;
    
    public class RedMenuButton extends Application {
    
        @Override
        public void start(Stage primaryStage) {
            final StackPane root = new StackPane();
            final MenuButton menuButton = new MenuButton("Menu");
            menuButton.getItems().addAll(new MenuItem("Item 1"), new MenuItem("Item 2"), new MenuItem("Item 3"));
            root.getChildren().add(menuButton);
    
            final Scene scene = new Scene(root, 250, 150);
            primaryStage.setScene(scene);
            primaryStage.show();
    
            menuButton.lookup(".arrow").setStyle("-fx-background-color: red;");
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }
    

    更新:但这是一个更好的解决方案(如果夏令时没有扰乱我的睡眠,我可能第一次会得到这个解决方案;)

    import javafx.application.Application;
    import javafx.scene.Scene;
    import javafx.scene.control.MenuButton;
    import javafx.scene.control.MenuItem;
    import javafx.scene.layout.StackPane;
    import javafx.stage.Stage;
    
    public class RedMenuButton extends Application {
    
        @Override
        public void start(Stage primaryStage) {
            final StackPane root = new StackPane();
            final MenuButton menuButton = new MenuButton("Menu");
            menuButton.getItems().addAll(new MenuItem("Item 1"), new MenuItem("Item 2"), new MenuItem("Item 3"));
            root.getChildren().add(menuButton);
    
            menuButton.setStyle("-fx-mark-color: red");
    
            final Scene scene = new Scene(root, 250, 150);
            primaryStage.setScene(scene);
            primaryStage.show();
        }
    
        public static void main(String[] args) {
            launch(args);
        }
    }