2017-03-21 2 views
1

2つのfxmlファイルがあります。例A.fxml。 B.fxml。私は2つのコントローラを持っています。 ACController(A.fxml)BController(B.fxml)。 fxmlとB fxmlには、Sceneまたはfxmlを変更する変更ボタンがあります。これはボタンコードです。JavaFx変更ウィンドウ、新しいコントローラなしコンストラクタ

try { 
     FXMLLoader loader = new FXMLLoader(getClass().getResource("/infoLibrary/view/A.fxml")); 
     Parent root = loader.load(); 
     Scene scene = new Scene(root); 
     Stage stage = (Stage)((Node)event.getSource()).getScene().getWindow(); 
     stage.setScene(scene); 
     stage.show(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 

BControllerの変更ボタンと同じコードです。変更ボタンをクリックすると、変更が反映されます。しかし、毎回initメソッドとコントローラcontructersも動作します。ユーザーが新しいコンストラクタを使用して毎回fxml javafxを変更したとき。新しいコントローラのコンストラクタを使用せずにウィンドウを変更するにはどうすればよいですか?

答えて

0

は、ビューモデルを使用してください:あなたのAControllerで今

public class ViewModel { 

    public enum View {A, B} 

    private final ObjectProperty<View> currentView = new SimpleObjectProperty<>(View.A); 

    public ObjectProperty<View> currentViewProperty() { 
     return currentView ; 
    } 

    public final View getCurrentView() { 
     return currentViewProperty().get(); 
    } 

    public final View setCurrentView(View view) { 
     currentViewProperty().set(view); 
    } 

} 

行います

public class AController { 

    private ViewModel viewModel ; 

    public void setViewModel(ViewModel viewModel) { 
     this.viewModel = viewModel ; 
    } 

    // button handler: 
    @FXML 
    private void goToB(ActionEvent event) { 
     viewModel.setCurrentView(ViewModel.View.B); 
    } 
} 

BControllerも同様です。今2つのFXMLファイルは一度だけロードされている

Stage stage = ... ; // maybe it's the primary stage in start... 
Scene scene = new Scene(); 
ViewModel viewModel = new ViewModel(); 

FXMLLoader aLoader = new FXMLLoader(getClass().getResource("/infoLibrary/view/A.fxml")); 
Parent a = aLoader.load(); 
AController aController = aLoader.getController(); 
aController.setViewModel(viewModel); 

FXMLLoader bLoader = new FXMLLoader(getClass().getResource("/infoLibrary/view/B.fxml")); 
Parent b = bLoader.load(); 
BController bController = bLoader.getController(); 
bController.setViewModel(viewModel); 

scene.rootProperty().bind(Bindings.createObjectBinding(() -> { 
    if (viewModel.getCurrentView() == ViewModel.View.A) { 
     return a ; 
    } else if (viewModel.getCurrentView() == ViewModel.View.B) { 
     return b ; 
    } else { 
     return null ; 
    } 
}, viewModel.currentViewProperty()); 

stage.setScene(scene); 
stage.show(); 

(:

最後に、あなたは(あなたのstart()方法では例えば、どこか似た)1回だけ実行され、以下のようなもので、すべてを設定しますコントローラーは一度だけ作成され、そのメソッドは一度だけ呼び出されるinitialize())。切り替えは、ViewModelの状態を変更してその状態を観察することによって管理されるため、モデルの状態が変化したときにシーンのルートが変更されます。

ViewModel.java:

package sceneswitcher; 

import javafx.beans.property.ObjectProperty; 
import javafx.beans.property.SimpleObjectProperty; 

public class ViewModel { 

    public enum View {A, B} 

    private final ObjectProperty<View> currentView = new SimpleObjectProperty<>(View.A); 

    public ObjectProperty<View> currentViewProperty() { 
     return currentView ; 
    } 

    public final View getCurrentView() { 
     return currentViewProperty().get(); 
    } 

    public final void setCurrentView(View view) { 
     currentViewProperty().set(view); 
    } 

} 

AController.java:

package sceneswitcher; 

import javafx.event.ActionEvent; 
import javafx.fxml.FXML; 
import javafx.scene.control.TextField; 

public class AController { 

    private ViewModel viewModel ; 

    @FXML 
    private TextField textField ; 

    public void setViewModel(ViewModel viewModel) { 
     this.viewModel = viewModel ; 
    } 

    // button handler: 
    @FXML 
    private void goToB(ActionEvent event) { 
     viewModel.setCurrentView(ViewModel.View.B); 
    } 

    public String getText() { 
     return textField.getText(); 
    } 
} 

A.fxml:

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

<?import javafx.scene.layout.VBox?> 
<?import javafx.scene.control.Label?> 
<?import javafx.scene.control.TextField?> 
<?import javafx.scene.control.Button?> 

<VBox fx:controller="sceneswitcher.AController" spacing="5" alignment="CENTER" 
     xmlns:fx="http://javafx.com/fxml/1"> 

    <Label text='This is view A'/> 
    <TextField fx:id="textField" /> 
    <Button onAction="#goToB" text="Go to view B"/> 
</VBox> 

BController.javaここ

は完了ですSSCCE :

package sceneswitcher; 

import javafx.event.ActionEvent; 
import javafx.fxml.FXML; 
import javafx.scene.control.TextArea; 

public class BController { 
    private ViewModel viewModel ; 

    @FXML 
    private TextArea textArea ; 

    public void setViewModel(ViewModel viewModel) { 
     this.viewModel = viewModel ; 
    } 

    // button handler: 
    @FXML 
    private void goToA(ActionEvent event) { 
     viewModel.setCurrentView(ViewModel.View.A); 
    } 

    public String getText() { 
     return textArea.getText(); 
    } 
} 

B.fxml:

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

<?import javafx.scene.layout.VBox?> 
<?import javafx.scene.control.Label?> 
<?import javafx.scene.control.TextArea?> 
<?import javafx.scene.control.Button?> 

<VBox fx:controller="sceneswitcher.BController" spacing="5" alignment="CENTER" 
     xmlns:fx="http://javafx.com/fxml/1"> 

    <Label text="This is view B"/> 
    <TextArea fx:id="textArea" /> 
    <Button onAction="#goToA" text="Go to View A"/> 
</VBox> 

Main.java:

package sceneswitcher; 

import java.io.IOException; 

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

public class Main extends Application { 

    @Override 
    public void start(Stage primaryStage) throws IOException { 
     ViewModel viewModel = new ViewModel(); 

     FXMLLoader aLoader = new FXMLLoader(getClass().getResource("A.fxml")); 
     Parent a = aLoader.load(); 
     AController aController = aLoader.getController(); 
     aController.setViewModel(viewModel); 

     FXMLLoader bLoader = new FXMLLoader(getClass().getResource("B.fxml")); 
     Parent b = bLoader.load(); 
     BController bController = bLoader.getController(); 
     bController.setViewModel(viewModel); 

     Scene scene = new Scene(a, 400, 400); 

     scene.rootProperty().bind(Bindings.createObjectBinding(() -> { 
      if (viewModel.getCurrentView() == ViewModel.View.A) { 
       return a ; 
      } else if (viewModel.getCurrentView() == ViewModel.View.B) { 
       return b ; 
      } else { 
       return null ; 
      } 
     }, viewModel.currentViewProperty())); 

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

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

uがこのような例のプロジェクトを持っていますか?または、簡単なMavenプロジェクトを作成できますか? fxmlおよびB fxml ACコントローラBController。私はあまりにも多くのことを期待して、私は知っているしかし、もしあなたがそれをしたら、私は感謝しています。 –

+0

@VolkanOkçu完全な例で更新されました。 –

+0

ありがとうございます。私はこれに感謝しています。 –

関連する問題