简体   繁体   中英

How to modify MenuButton arrow color by JavaFX not FXML CSS?

i am trying to modify color of MenuButton arrow , using JavaFX code not by CSS .

i found it inside 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";
}

i tried to use something like that :

menubutton.lookup(".arrow");

but it throw NullPointerException

and when i do that :

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

it out put that only: menu-button only.

so can any one give me the way to modify it using Java without using CSS ??

This works:

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);
    }
}

Update: But this is a better solution (which I probably would have got first time if daylight savings hadn't messed with my sleep ;)).

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);
    }
}

There are several ways to do this, here are four. The code is Jython with JavaFX. You can edit this code to meet your needs.


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.

EG #1

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

EG#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

Don't configure the ComboBox Arrow by CSS, instead, do it programmatically and change the Regions SVG Shape

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)

Configure the ComboBox Arrow by CSS and change the Regions SVG Shape

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

Configure the ComboBox Arrow by CSS but instead, merely hide the arrow by setting the transparency/opacity values and set a background.

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

Don't configure the ComboBox Arrow by CSS, instead, do it programmatically and merely hide the arrow by setting the transparency/opacity values and set a background.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM