Edit JavaFX CSS at runtime

谁说我不能喝 提交于 2021-02-17 20:54:25

问题


I'm creating a CSS stylesheet for a JavaFX 8 application.

I'm repeating these steps several times:

  1. Edit the CSS
  2. Run the application and see the changes
  3. Stop the application

I found this approach very time-consuming and looking for something smarter.

Is it possibile to edit the CSS of my JavaFX application while running and see the result in real-time?

I'm looking for something like the Inspect tool of Google Chrome.

This can be partially reached by using Oracle Scene Builder. In fact I can load a CSS file and run the preview. Any change to the CSS file is correctly shown in the preview without the need to restart.

Unfortunately that's just a preview: many components are empty/uninitialized. Sure this is anyway very helpful, but many refinements require the real application running.


回答1:


You will have to change using getStylesheets() / setStyle() etc.

In the example below I had to use a temp file as I am changing the CSS of the scene, when using into single components this is not necessary as you can change directly in the components.

enter image description here

You may download this example on gist.

Test.java

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Test extends Application{

    @Override
    public void start(Stage primaryStage) throws Exception {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("doc.fxml"));
        Parent root = (Parent)loader.load();
        CSSController myController = loader.getController();
        Scene scene = new Scene(root);
        myController.setScene(scene);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    public static void main(String[] args) {
        launch(args);
    }

}

CSSController.java

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.net.URL;
import java.util.ResourceBundle;

import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;

public class CSSController implements Initializable{
    private Scene scene;
    @FXML TextArea cssContent;
    @FXML Button defineCSSButton;
    @Override
    public void initialize(URL location, ResourceBundle resources) {
        defineCSSButton.setOnAction(new EventHandler<ActionEvent>(){
            @Override
            public void handle(ActionEvent event) {
                String css = cssContent.getText();
                try{
                    File temp = new File("tempfile.css"); 
                    temp.delete();
                    temp.createNewFile();
                    BufferedWriter bw = new BufferedWriter(new FileWriter(temp));
                    bw.write(css);
                    bw.close();
                    String url = "tempfile.css";
                    scene.getStylesheets().add(temp.toURI().toString());
                }catch(Exception e){
                    e.printStackTrace();
                }
            }
        });    
    }
    public void setScene(Scene scene) { this.scene = scene; }
}

doc.fxml

<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.shape.*?>

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity"
    minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0"
    prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="CSSController">
    <children>
        <TextArea fx:id="cssContent" layoutX="14.0" layoutY="26.0"
            prefHeight="292.0" prefWidth="319.0" />
        <Label layoutX="22.0" layoutY="6.0" text="Define your CSS here:" />
        <Button fx:id="defineCSSButton" layoutX="14.1875" layoutY="333.5"
            mnemonicParsing="false" text="Define CSS" />
        <Line endY="400.0" layoutX="332.0" />
        <Label layoutX="418.0" layoutY="15.0" text="Components:" />
        <ChoiceBox layoutX="343.0" layoutY="48.0" prefWidth="150.0" />
        <ColorPicker layoutX="343.3759765625" layoutY="86.0" />
        <CheckBox layoutX="347.6650390625" layoutY="123.0"
            mnemonicParsing="false" text="CheckBox" />
        <MenuButton layoutX="343.37109375" layoutY="159.5"
            mnemonicParsing="false" text="MenuButton">
            <items>
                <MenuItem mnemonicParsing="false" text="Action 1" />
                <MenuItem mnemonicParsing="false" text="Unspecified Action" />
                <MenuItem mnemonicParsing="false" text="Unspecified Action" />
                <CheckMenuItem mnemonicParsing="false" text="Unspecified Action" />
            </items>
        </MenuButton>
        <ProgressIndicator layoutX="347.9091796875" layoutY="200.01953125"
            progress="0.0" />
        <Slider layoutX="410.0" layoutY="213.01953125" />
        <ToggleButton layoutX="348.7421875" layoutY="254.0"
            mnemonicParsing="false" text="ToggleButton" />
    </children>
</AnchorPane>

Css in the screenshot:

.label{
-fx-font: 15px "System Bold";
-fx-text-fill: #FF0000;
}

.button{
    -fx-background-color:
        #c3c4c4,
        linear-gradient(#d6d6d6 50%, white 100%),
        radial-gradient(center 50% -40%, radius 200%, #e6e6e6 45%, rgba(230,230,230,0) 50%);
    -fx-background-radius: 30;
    -fx-background-insets: 0,1,1;
    -fx-text-fill: black;
    -fx-effect: dropshadow( three-pass-box , rgba(0,0,0,0.6) , 3, 0.0 , 0 , 1 );
}


来源:https://stackoverflow.com/questions/24762217/edit-javafx-css-at-runtime

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!