2015-03-24 62 views
-1

我目前正在研究一個需要我在場景之間前後切換的項目。我已經爲它編寫了一些代碼,但它並不像我想要的那麼優雅,尤其是當我在它們之間切換時幾乎沒有閃爍,有時甚至是我生成的按鈕只是消失而再次出現時另一場景已經產生。此外,我用於我的應用程序的佈局並沒有真正解決,我認爲使用FXML可能不適合我正在做的事情。如何在單個階段中改變動態生成的JavaFX場景?

謝謝。

這是我使用的是什麼樣的場景之間切換:

void changeScene(Stage stage,Scene scene){ 
    stage.setScene(scene); 
    primaryStage.setFullScreen(true); 
} 
+0

什麼實際問題? – 2015-03-24 22:11:54

+0

如何在場景之間切換,最好不使用FXML。 – 2015-03-24 22:42:05

+0

問題的答案是,你要麼在'Stage'上調用'setScene(...)',並且傳入一個新的'Scene',或者在現有的'Scene上調用'setRoot(...)' ',並傳入場景圖的新根。我有點懷疑這並不會幫助你,但如果你想得到更有幫助的答案,你需要在你的問題中提供更多的細節。 – 2015-03-25 00:59:06

回答

0

我承擔的「場景切換」你的意思是要改變現有窗口的全部內容。

有兩個(非常)略有不同的方法可以做到這一點。創建一個新的Scene並將其傳遞給StagesetScene(...)方法。或者創建作爲新UI的根的Parent(通過FXML或其他方式),並將其傳遞給現有的ScenesetRoot(...)方法。我沒有看到其中一個的真正優勢。

這是第二個選項的最小實現。 UI與問題無關:重要的部分是「登錄」按鈕(從登錄場景切換到主場景)和「註銷」按鈕(切換回)的事件處理程序。

import java.util.stream.IntStream; 

import javafx.application.Application; 
import javafx.beans.binding.Bindings; 
import javafx.beans.property.IntegerProperty; 
import javafx.beans.property.SimpleIntegerProperty; 
import javafx.geometry.HPos; 
import javafx.geometry.Insets; 
import javafx.geometry.Pos; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.Label; 
import javafx.scene.control.ListView; 
import javafx.scene.control.SplitPane; 
import javafx.scene.control.TextField; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.ColumnConstraints; 
import javafx.scene.layout.GridPane; 
import javafx.scene.layout.Priority; 
import javafx.scene.text.Font; 
import javafx.scene.text.FontWeight; 
import javafx.stage.Stage; 

public class MinimalSceneSwitchingExample extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     LoginView loginView = new LoginView(); 
     Scene scene = new Scene(loginView.getView(), 400, 400); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    public static class LoginView { 

     private final IntegerProperty loginAttempts ; 

     private final GridPane view ; 

     public LoginView() { 

      view = new GridPane(); 

      TextField usernameTF = new TextField("user"); 
      TextField passwordTF = new TextField("pass"); 

      // Login button switches to main view: 
      Button loginButton = new Button("Login"); 
      loginButton.setOnAction(event -> { 
       if (usernameTF.getText().equalsIgnoreCase("user") 
        && passwordTF.getText().equalsIgnoreCase("pass")) { 

        // *** Switch to main view: *** 

        Parent mainView = new MainView().getView(); 
        view.getScene().setRoot(mainView); 

       } else { 
        loginAttempts.set(loginAttempts.get()+1); 
       } 
      }); 

      // just set up login UI... irrelevant to this example: 


      loginAttempts = new SimpleIntegerProperty(); 

      usernameTF.setPromptText("Hint: user"); 
      passwordTF.setPromptText("Hint: pass"); 

      view.addRow(0, new Label("Username:"), usernameTF); 
      view.addRow(1, new Label("Password:"), passwordTF); 

      Label loginErrorMessage = new Label(); 

      loginErrorMessage.textProperty().bind(
        Bindings.when(loginAttempts.isEqualTo(0)) 
        .then("") 
        .otherwise(Bindings.format("Login incorrect (Attempts: %d)", 
          loginAttempts))); 

      view.add(loginErrorMessage, 0, 2, 2, 1); 

      view.add(loginButton, 0, 3, 2, 1); 

      ColumnConstraints leftCol = new ColumnConstraints(); 
      leftCol.setHgrow(Priority.NEVER); 
      leftCol.setHalignment(HPos.RIGHT); 
      ColumnConstraints rightCol = new ColumnConstraints(); 
      rightCol.setHgrow(Priority.ALWAYS); 
      rightCol.setHalignment(HPos.LEFT); 

      view.getColumnConstraints().addAll(leftCol, rightCol); 
      GridPane.setHalignment(loginErrorMessage, HPos.CENTER); 
      GridPane.setHalignment(loginButton, HPos.CENTER); 

      view.setHgap(10); 
      view.setVgap(16); 

      view.setAlignment(Pos.CENTER); 
     } 

     public Parent getView() { 
      return view ; 
     } 

    } 

    public static class MainView { 

     private BorderPane view ; 

     public MainView() { 

      view = new BorderPane(); 

      // *** logout button switches back to a login view: *** 

      Button logoutButton = new Button("Log out"); 
      logoutButton.setOnAction(event -> 
       view.getScene().setRoot(new LoginView().getView())); 

      // Arbitrary UI, irrelevant to this example: 

      SplitPane splitPane = new SplitPane(); 
      ListView<String> listView = new ListView<>(); 
      IntStream.rangeClosed(1, 10) 
       .mapToObj(Integer::toString) 
       .map("Item "::concat) 
       .forEach(listView.getItems()::add); 

      Label bigLabel = new Label(); 
      bigLabel.textProperty().bind(
        listView.getSelectionModel().selectedItemProperty()); 
      bigLabel.setFont(Font.font("Verdana", FontWeight.BOLD, 18)); 
      BorderPane.setAlignment(bigLabel, Pos.CENTER); 
      BorderPane.setMargin(bigLabel, new Insets(10)); 

      Label details = new Label(); 
      details.textProperty().bind(
       Bindings.when(
         listView.getSelectionModel().selectedItemProperty().isNull()) 
        .then("") 
        .otherwise(Bindings.format("This is where you would display " 
         + "all sorts of details about %1$s. " 
         + "If %1$s were really a model object, you " 
         + "might have a GridPane displaying all its " 
         + "properties, for example.", 
         listView.getSelectionModel().selectedItemProperty()))); 

      details.setWrapText(true); 

      BorderPane detailsPane = new BorderPane(details, bigLabel, null, null, null); 

      splitPane.getItems().addAll(listView, detailsPane); 

      view.setCenter(splitPane); 
      view.setBottom(logoutButton); 

      BorderPane.setAlignment(logoutButton, Pos.CENTER); 
      BorderPane.setMargin(logoutButton, new Insets(8)); 
      BorderPane.setMargin(splitPane, new Insets(16)); 
     } 

     public Parent getView() { 
      return view ; 
     } 
    } 

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

我遇到的問題是我不知道如何改變舞臺的內容;我現在正在做的是創造一個新場景每次我在場景之間「改變」。 – 2015-03-25 09:17:29

+0

我發佈的答案肯定會告訴你如何在一個場景的內容之間進行切換? 「如何在場景之間切換,最好不使用FXML?」:這正是代碼所做的,不是? – 2015-03-25 09:24:20

+0

這意味着我每次需要更改屏幕時都必須調用.setScene,這會導致屏幕調整大小並閃爍幾秒鐘。 – 2015-03-25 09:29:34