2013-07-21 10 views
10

È possibile modificare css per un'applicazione JavaFX mentre è in esecuzione?javafx cambia css in fase di esecuzione

L'effetto che sto cercando è cambiare skin o temi con un clic di un pulsante.

L'interfaccia utente è in un file FXML se questo fa alcuna differenza.

ho cercato

Scene.getStylesheets() 
    .add(getClass().getResource(skinFileName).toExternalForm()); 

che non ha alcun effetto.

grazie

risposta

9

Dovrebbe avere l'effetto. Prova questo codice demo completa:

public class CssThemeDemo extends Application { 

    private String theme1Url = getClass().getResource("theme1.css").toExternalForm(); 
    private String theme2Url = getClass().getResource("theme2.css").toExternalForm(); 

    @Override 
    public void start(Stage primaryStage) { 
     StackPane root = new StackPane(); 
     final Scene scene = new Scene(root, 300, 250); 
     System.out.println("scene stylesheets: " + scene.getStylesheets()); 
     scene.getStylesheets().add(theme1Url); 
     System.out.println("scene stylesheets: " + scene.getStylesheets()); 

     final Button btn = new Button("Load Theme 1"); 
     btn.getStyleClass().add("buttonStyle"); 
     btn.setOnAction(new EventHandler<ActionEvent>() { 
      @Override 
      public void handle(ActionEvent event) { 
       scene.getStylesheets().remove(theme2Url); 
       System.out.println("scene stylesheets on button 1 click: " + scene.getStylesheets()); 
       if(!scene.getStylesheets().contains(theme1Url)) scene.getStylesheets().add(theme1Url); 
       System.out.println("scene stylesheets on button 1 click: " + scene.getStylesheets()); 
      } 
     }); 

     final Button btn2 = new Button("Load Theme 2"); 
     btn2.getStyleClass().add("buttonStyle"); 
     btn2.setOnAction(new EventHandler<ActionEvent>() { 
      @Override 
      public void handle(ActionEvent event) { 
       scene.getStylesheets().remove(theme1Url); 
       System.out.println("scene stylesheets on button 2 click: " + scene.getStylesheets()); 
       if(!scene.getStylesheets().contains(theme2Url)) scene.getStylesheets().add(theme2Url); 
       System.out.println("scene stylesheets on button 2 click: " + scene.getStylesheets()); 
      } 
     }); 

     ComboBox<String> comboBox = new ComboBox<String>(FXCollections.observableArrayList("Just", "another", "control")); 
     root.getChildren().add(VBoxBuilder.create().spacing(10).children(btn, btn2, comboBox).build()); 

     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

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

theme1 css:

.root{ 
    -fx-font-size: 14pt; 
    -fx-font-family: "Tahoma"; 
    -fx-base: #DFB951; 
    -fx-background: #A78732; 
    -fx-focus-color: #B6A678; 
} 

.buttonStyle { 
    -fx-text-fill: #006464; 
    -fx-background-color: #DFB951; 
    -fx-border-radius: 20; 
    -fx-background-radius: 20; 
    -fx-padding: 5; 
} 

theme2 css:

.root{ 
    -fx-font-size: 16pt; 
    -fx-font-family: "Courier New"; 
    -fx-base: rgb(132, 145, 47); 
    -fx-background: rgb(225, 228, 203); 
} 

.buttonStyle { 
    -fx-text-fill: red; 
    -fx-background-color: lightcyan; 
    -fx-border-color: green; 
    -fx-border-radius: 5; 
    -fx-padding: 3 6 6 6; 
} 

Nota gli stessi selettori CSS denominati sia in theme1 e theme2 file CSS.

2

Si può anche provare questo pezzo di codice (semplice e veramente illustrativo):

  • un contenitore per esso: ho scelto BorderPane.
  • Aggiungi una scena principale per la tua applicazione.
  • Una barra dei menu con un set di elementi a seconda dell'aspetto dell'applicazione.
  • E articolo sulla barra dei menu.
BorderPane rootPane = new BorderPane(); 
Parent content = FXMLLoader.load(getClass().getResource("sample.fxml")); 
rootPane.setCenter(content); 
Scene scene = new Scene(root, 650, 550, Color.WHITE); 
// Menu bar 
MenuBar menuBar = new MenuBar(); 

// file menu 
Menu fileMenu = new Menu("_File"); 
MenuItem exitItem = new MenuItem("Exit"); 
exitItem.setAccelerator(new KeyCodeCombination(KeyCode.X, KeyCombination.SHORTCUT_DOWN)); 
exitItem.setOnAction(ae -> Platform.exit()); 

fileMenu.getItems().add(exitItem); 
menuBar.getMenus().add(fileMenu); 

// Look and feel menu 
Menu themeMenu = new Menu("_Theme"); 
themeMenu.setMnemonicParsing(true); 
menuBar.getMenus().add(themeMenu); 
rootPane.setTop(menuBar); 


MenuItem theme1 = new MenuItem("Theme 1"); 
theme1.setOnAction(ae -> { 
      scene.getStylesheets().clear(); 
      setUserAgentStylesheet(null); 
      scene.getStylesheets() 
        .add(getClass() 
          .getResource("theme1.css") 
          .toExternalForm()); 
}); 

MenuItem theme2 = new MenuItem("Theme 2"); 
     theme2.setOnAction(ae -> { 
      scene.getStylesheets().clear(); 
      setUserAgentStylesheet(null); 
      scene.getStylesheets() 
        .add(getClass() 
          .getResource("theme2.css") 
          .toExternalForm()); 
}); 


themeMenu.getItems() 
       .addAll(theme1, 
         theme2); 

primaryStage.setScene(scene); 
primaryStage.show(); 

supposto che avete i vostri due file CSS nella cartella della classe dove potrete chiamare questo codice con il corrispondente nome theme1.css e theme2.css.

Ora è possibile passare da un tema all'altro mentre l'applicazione è in esecuzione.