2017-05-11 5 views
0

私はチェッカーゲームをデザインしています。ゲームが終了すると、新しいゲームを開始するか終了する可能性のある新しいウィンドウが開きます。私はJavaFXについてあまりよく分かりませんし、コードを動作させるためにしばらく試していましたが、私は成功せずに立ちました...Controller JavaFXから新しいシーンを開く

私のボードはfxmlとして表示されませんファイルがjavacodeで作成されていて、私のborderPaneの中央に置かれています。 borderPaneの先頭はfxml-fileです。ゲームが終わった後に続いて、他のウィンドウには、また別のFXMLファイルで次のようにこのFXMLファイル用

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

<?import javafx.scene.text.*?> 
<?import javafx.geometry.*?> 
<?import javafx.scene.control.*?> 
<?import java.lang.*?> 
<?import javafx.scene.layout.*?> 
<?import javafx.scene.layout.AnchorPane?> 

<Pane fx:id="paneMenu" nodeOrientation="LEFT_TO_RIGHT" prefHeight="160.0" prefWidth="240.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.GameMenuController"> 

<children> 
<Button fx:id="buttonRestart" layoutX="15.0" layoutY="122.0" mnemonicParsing="false" onAction="#restart" prefHeight="27.0" prefWidth="90.0" text="New Game" /> 
    <Button fx:id="buttonQuit" layoutX="139.0" layoutY="122.0" mnemonicParsing="false" onAction="#quit" prefHeight="27.0" prefWidth="90.0" text="Quit" /> 
    <Label fx:id="labelWinner" alignment="CENTER" contentDisplay="CENTER" layoutX="23.0" layoutY="80.0" prefHeight="17.0" prefWidth="190.0" text="Label" textAlignment="CENTER" /> 
    <Text layoutX="50.0" layoutY="47.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Game over!" textAlignment="CENTER"> 
    <font> 
     <Font size="26.0" /> 
    </font> 
    </Text> 
    </children> 
    <padding> 
    <Insets bottom="10.0" right="10.0" /> 
</padding> 
</Pane> 

私のコントローラクラスが見えます:

public class GameMenuController implements Initializable { 

public GameMenuController(Checkers model) { 
    this.content = model; 
} 

Checkers content; 

@FXML 
private Label labelWinner; 

@FXML 
private Button buttonRestart; 

@FXML 
private Button buttonQuit; 

@FXML 
private Pane paneMenu; 

BooleanProperty doRestart = new SimpleBooleanProperty(false); 

@FXML 
void restart(ActionEvent event) { 
    content.cleanup(); 
    doRestart.set(true); 
} 

@FXML 
void quit(ActionEvent event) { 
    System.exit(0); 
} 

@Override 
public void initialize(URL location, ResourceBundle resources) { 
    labelWinner.setText("Winner here."); 
    labelWinner.textProperty().bind(Bindings.createStringBinding(() -> { 
     String s = " "; 
     if (...); 
     return s; 
    }, content.whiteTurnProp)); 
} 

} 

そして最後に、私の中でメインクラス私は、新しいシーンを再作成するために、ChangeListenerを値doRestartに追加したいと思っていました。以来

public class Main extends Application{ 

Checkers content = new Checkers(); 
BorderPane border = new BorderPane(); 
Pane paneBoard = new Pane(); 
FXMLLoader loader1 = new FXMLLoader(); 
FXMLLoader loader2 = new FXMLLoader(); 

@Override 
public void start(Stage primaryStage) throws Exception { 

    loader1.setLocation(getClass().getResource("sample.fxml")); 
    loader1.setControllerFactory(new Callback<Class<?>, Object>() { 
     @Override 
     public Object call(Class<?> aClass) { 
      return new SampleController(content); 
     } 
    }); 

    loader2.setLocation(getClass().getResource("GameMenu.fxml")); 
    loader2.setControllerFactory(new Callback<Class<?>, Object>() { 
     @Override 
     public Object call(Class<?> aClass) { 
      return new GameMenuController(content); 
     } 
    }); 
    GameMenuController gameMenuControl = loader2.getController(); 

    Scene scene = new Scene(startGame()); 
    primaryStage.setTitle("Checkers"); 
    primaryStage.setScene(scene); 
    primaryStage.show(); 

    content.gameOver.addListener(new ChangeListener<Boolean>() { 
      @Override 
      public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { 
       try { 
        scene.setRoot(loader2.load()); 
        primaryStage.setHeight(180); 
        primaryStage.setWidth(240); 
       } catch (IOException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      } 

     }); 

    gameMenuControl.doRestart.addListener(new ChangeListener<Boolean>() { 
     @Override 
     public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { 
      if(newValue) { 
      scene.setRoot(startGame()); 
      primaryStage.setHeight(scene.getHeight()); 
      primaryStage.setWidth(scene.getWidth()); 
      gameMenuControl.doRestart.set(false); 
      } 
     } 
    }); 
} 

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

    paneBoard.setPrefSize(Checkers.WIDTH * Checkers.TILE_SIZE, Checkers.HEIGHT * Checkers.TILE_SIZE); 
    paneBoard.getChildren().addAll(content.tileGroup, content.pieceGroup); 

    for (int y = 0; y < Checkers.HEIGHT; y++) { 
     for (int x = 0; x < Checkers.WIDTH; x++) { 
      Tile tile = new Tile((x + y) % 2 == 0, x, y); 
      Checkers.board[y][x] = tile; 

      content.tileGroup.getChildren().add(tile); 

      Piece piece = null; 

      if (y <= 3 && (x + y) % 2 != 0) { 
       piece = content.makePiece(PieceType.BLACK, x, y); 
      } 

      if (y >= 6 && (x + y) % 2 != 0) { 
       piece = content.makePiece(PieceType.WHITE, x, y); 
      } 

      if (piece != null) { 
       tile.setPiece(piece); 
       content.pieceGroup.getChildren().add(piece); 
      } 
     } 
    } 

    return paneBoard; 
} 

protected BorderPane startGame() { 
    try { 
     border.setTop(loader1.load()); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    border.setCenter(createContent()); 

    return border; 
} 

} 

私は、私はここに可能な限りに与えられたヒントをできるだけ多くで動作するようにしようとしてきた私のコードは混乱があることをかなり確信している、しかし:

私のメインクラスは次のようになります私はまだこれに新しいスーパーです、私は本当にそれについてすべてを行く方法を知りません。

この変更リスナー(これはまだ動作しませんが、IamはNullPointerExceptionを取得します)を使用する代わりに、コントローラから直接ビューを変更したいと考えています。私はこれについてどうやって行くのですか?

1)Factoryを介してコントローラを作成するのではなく、モデルチェッカにアクセスできるようにすることはできますか? (すべてのゲームロジックがそこに保存されています)

2)基本的に最初のウィンドウを再作成するにはどうすればいいですか? (startGame()で作成)

ありがとうございます! ベスト、 リサ

答えて

1

あなたはloader2.load()を呼び出す前GameMenuController gameMenuControl = loader2.getController()を呼んでいます。コントローラーはロードプロセスの一部として作成されるので、gameMenuControlはnullになります。

loader2.load()を呼び出した直後に、loader2.getController()gameMenuControl.doRestart.addListener(...)にコールを転送するだけで済みます。

また、コントローラファクトリに委任する代わりに、コントローラを自分で作成することもできます。 FXMLファイルからfx:controller属性を削除し、次に実行します。大丈夫

@Override 
public void start(Stage primaryStage) throws Exception { 

    // You can make similar changes to loader1 if you want... 

    loader2.setLocation(getClass().getResource("GameMenu.fxml")); 

    GameMenuController gameMenuControl = new GameMenuController(content) ; 

    gameMenuControl.doRestart.addListener(new ChangeListener<Boolean>() { 
     @Override 
     public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { 
      if(newValue) { 
      scene.setRoot(startGame()); 
      primaryStage.setHeight(scene.getHeight()); 
      primaryStage.setWidth(scene.getWidth()); 
      gameMenuControl.doRestart.set(false); 
      } 
     } 
    }); 

    loader2.setController(gameMenuControl); 

    content.gameOver.addListener(new ChangeListener<Boolean>() { 
      @Override 
      public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) { 
       try { 
        scene.setRoot(loader2.load()); 
        primaryStage.setHeight(180); 
        primaryStage.setWidth(240); 
       } catch (IOException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      } 

     }); 

    Scene scene = new Scene(startGame()); 
    primaryStage.setTitle("Checkers"); 
    primaryStage.setScene(scene); 
    primaryStage.show(); 


} 
+0

は、あなたの助けのためにどうもありがとうございます! :) – Lisa

関連する問題