質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
JavaFX

JavaFXとは、Java仮想マシン上で動作するリッチインターネットアプリケーション (RIA) のGUIライブラリです。Swingとは異なり、FXMLと呼ばれる XMLとCSSを併用してデザインを記述します。

Q&A

解決済

1回答

3385閲覧

シーングラフを更新する方法(子要素の削除?)

hilty8

総合スコア15

JavaFX

JavaFXとは、Java仮想マシン上で動作するリッチインターネットアプリケーション (RIA) のGUIライブラリです。Swingとは異なり、FXMLと呼ばれる XMLとCSSを併用してデザインを記述します。

0グッド

0クリップ

投稿2018/03/20 12:29

編集2018/03/20 23:21

JavaFXを独学で学んでいる者です。

将棋のようなゲームを作ろうとしています。コマを選択し、移動先を選択した際に、処理結果が反映されない事態が生じており困っています。
GridPaneを継承したGameBoardクラスに対して、盤面の状態を示したint型の二重配列を引数にして渡すことで、描画する方法を採用しているのですが、前回の盤面の状態が残ったまま、次のターンの処理結果が表示されてしまいます。

試したこと1

調べた結果、remove()ないしremoveAll() というメソッドがあることを知りましたが、期待通りの結果にはなりませんでした。
下記のコードには、試したremove()も書いてあります。

試したこと2

GameBoardクラスのインスタンスを新たに生成するのではなく、rendering()というメソッドを用いることで、同じインスタンスを使いまわすような設定にしてみました。
GameBoardクラスのインスタンスを新たに生成した場合、移動の結果が全く反映されなかったので、
Mainクラスで選択した描画の対象から外れたのだと考えています。

わかりにくいところなどは指摘していただければ、なるべく早く追記します。
宜しくお願い致します。

追記(18/03/21 - 00:20)

・PieceTypeというのは、個人的に定義しているenumクラスです。コマなし、コマA~コマC、の計4つを持ちます。
・盤面の描画の際、本当はint[][] ではなくPieceType[][] を用いていたので、実際のコードに沿った形に修正しました。
・先ほどまではGameBoardクラスと表記していましたが、コードではBoardLatticeクラスという名前で使用していたので、実際のコードに沿って名前を修正しました。
・MVCのModel部分であるLogManagerクラスの挙動は、標準出力を用いて1つずつ確認したので、このクラスにエラーは無いと判断しています。
見直しをしたので、syntaxErrorは無いと思いますが、ミスがあれば即時対応します。
宜しくお願い致します。

追記2 問題箇所の予想(対処中) (18/03/21 - 08:10)

MVCにおけるViewを担当している、マス目の処理を担うSquareクラス(extends StackPane)の処理に関して、
前のターンにBoardLatticeインスタンスに追加したSquareインスタンスを更新するのではなく、
その上に新たなSquareインスタンスを追加していることが原因だと考えています。
そのため、BoardLatticeクラスの描画仕様を変更するつもりでいます。
描画の方法に関して助言頂ければ幸いです。
宜しくお願い致します。

java

1public class Main extends Application { 2@Override 3public void start(Stage stage) throws Exception { 4 Controller controller = new Controller();// MVCモデルのコントローラ 5 VBox root = new VBox(); 6 root.getChildren().add(controller.gameBoard); 7 (以下はStageSceneに追加しているだけなので省略) 8}

java

1//MVCのView部分1 - ゲーム盤 2public class BoardLattice extends GridPane { 3 private Boolean turnPlayer1 = true; 4 public IntegerProperty propertyRow = new SimpleIntegerProperty(-1); 5 public IntegerProperty propertyCol = new SimpleIntegerProperty(-1); 6 Square[][] squares; 7 8 public BoardLattice(PieceType[][] boardStatus, Boolean argsTurnPlayer1){ 9 rendering(boardStatus, argsTurnPlayer1); 10 } 11 12 public void rendering(PieceType[][] boardStatus, Boolean argsTurnPlayer1){ 13 turnPlayer1 = argsTurnPlayer1; 14 //描画の処理 15 squares = new Square[5][5]; 16 for(int i=0; i<5; i++){ 17 for(int j=0; j<5; j++){ 18 // 前回のターンの結果を消去した 19 super.getChildren().remove(squares[i][j]); 20 // ImageViewクラスを継承したPieceクラスのインスタンスを生成 21 Piece piece = new Piece(boardStatus[i][j]); 22 squares[i][j].getChildren().add(piece); 23 super.add(squares[i][j], i, j); 24 25 int row = i; 26 int col = j; 27 squares[i][j].setOnMouseClicked(event -> { 28 propertyRow.setValue(row); 29 propertyCol.setValue(col); 30 }; 31 // 手番ではないPlayerの駒が載ったsquares[i][j]をクリックしてもEventが発生しないように設定 32 switch(boardStatus[i][j]){ 33 // 条件分岐のみ省略 34 squares[i][j].setDisable(true); 35 } 36 } 37 } 38 } 39}

java

1//MVCのView部分2 - 移動ボタンのコントローラクラス 2public class DirectionButtonController implements initializable { 3 // 移動ボタンが押されたとき、このコントローラクラスのStringPropertyの値に格納される 4 public static StringProperty direction = new SimpleStringProperty("have not choosen!"); 5 // FXML内に定義したボタン(Polygonクラス) 6 @FXML Polygon upButton; 7 // 移動ボタンにEventを実装 8 EventHandler<MouseEvent> upMethod = (event) -> { 9 direction.setValue("up"); 10 }; 11 @Override 12 public void initialize(URL url, ResourceBandle rb){ 13 upButton.setOnMouseClicked(upMethod); 14 } 15}

java

1//MVCのModel部分 2public class LogManager { 3 public Boolean turnPlayer1; 4 // 選択した駒の行、列の番号 5 public NumberBinding bindRow; 6 public NumberBinding bindCol; 7 // 駒の移動方向を指すStringProperty 8 public StringProperty direction = new SimpleStringProperty(""); 9 10 public int turn; 11 public PieceType[][][] mainLog = new PieceType[256][5][5]; // 256手番もあればゲームが終わる想定 12 public PieceType[][] tmpLog = new PieceType[5][5]; 13 14 public LogManager(){ 15 turn = 1; 16 turnPlayer1 = true; 17 initializeMainLog(); 18 } 19 public int[][] getLog(){ 20 return tmpLog; 21 } 22 // 以下の移動の処理に関しては期待通りの結果が出ているため、各メソッドの詳細は省略しています。 23 public void moveMethod(){ 24 // tmpLogを更新。 25 setTmpLog(); 26 //NumberBinding, StringPropertyの値を用いて移動処理を実行する 27 whichDirection(direction.getValue()); 28 // 実際の移動処理 29 movePiece(bindRow.intValue(), bindCol.intValue()); 30 // 処理結果を格納したtmpLogの値をMainLogに書き込み 31 updateMainLog(); 32 } 33 private void setTmpLog(){ 34 // mainLog[turn]をtmpLogにコピー(省略) 35 } 36 private void whichDirection(String str){ 37 // 移動処理に用いるint型の変数を設定(省略) 38 } 39 private void updateMainLog(){ 40 // ターン数+1 41 turn += 1; 42 // 処理結果を格納したtmpLogの値をMainLogに書き込み(省略) 43 // 手番の入れ替え 44 turnPlayer1 = !turnPlayer1; 45 } 46 47 private void initializeMainLog(){ 48 // MainLog[0], MainLog[1]の2つにおいて、初期状態のコマ配置を指定 49 } 50 51}

java

1public class Controller { 2 //MVCモデルにおける、View: BoardLattice、Model: LogManager 3 public BoardLattice boardLattice; 4 public LogManager logManager; 5 public GridPane directionButton; 6 7 public Controller() throws IOException { 8 logManager = new LogManager(); 9 boardLattice = new BoardLattice(logMangager.getLog()); 10 directionButton = FXMLLoader.load(getClass().getResource("DirectionButton.fxml")); 11 // Binding設定1 - 選択した駒を示す情報のBinding 12 logManager.bindRow = Bindings.add(boardLattice.propertyRow, 0); 13 logManager.bindCol = Bindings.add(boardLattice.propertyCol, 0); 14 // 移動ボタンのコントローラクラス、DirectionButtonControllerのStringPropertyと、logManagerのStringPropertyをBind 15 logManager.direction.bind(DirectionButtonController.direction); 16 // LogManagerのStringPropertyが更新されたとき、移動処理を実行(ChangeListenerをラムダ式で定義) 17 logManager.direction.addListener( (ObservableValue<? extends String> observable, String oldValue, String newValue) -> { 18 // logManager内の移動処理メソッドを実行 19 logManager.moveMethod(); 20 // boardLatticeの再描画 21 boardLattice.rendering(logManager.getLog(), logManager.turnPlayer1); 22 } 23 } 24}

java

1public class Square extends StackPane { 2 public Square(){ 3 super.setPrefSize(70,70); 4 // MouseOver,MouseExitのEventに従って背景を変化(省略) 5 } 6}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KSwordOfHaste

2018/03/20 13:07

コードの部分が省略されすぎていて原因が判断できません。再現するための100行程度の完全なコードを提示するのが一番です。原因に関係しないような処理は再現に必要な部分だけ残して消してしまいそれを提示するわけです。めんどくさいですが閲覧者の面倒さを減らすためには必要な手間だと思ってください。
hilty8

2018/03/20 13:19

承知しました。修正しておきます。
KSwordOfHaste

2018/03/20 14:11

例えばController#gameBoardが何者かなどコードの構造を把握するのに必要な情報に多々欠落があります。syntax errorも残っています。そのまま実行できるコードを提示していただければ時間の節約になると思うのですが。
hilty8

2018/03/20 14:21

わかりました。長くなりますが、殆ど情報を省略せずに記載することにします。
guest

回答1

0

自己解決

追記2の通り、Squareインスタンスを毎回生成する方法をやめ、ImageViewインスタンスを更新する方式に変更したところ、前ターンの結果を残すことなく動作できました。

投稿2018/03/21 02:15

hilty8

総合スコア15

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問