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

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

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

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

Q&A

解決済

2回答

1659閲覧

static修飾子を用いずに、他のコントロールが所持する情報を把握する方法

hilty8

総合スコア15

JavaFX

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

0グッド

1クリップ

投稿2018/03/04 08:04

編集2018/03/04 10:14

JavaFXを独学で学んでいるものです。やや混乱しているので、伝わりにくい箇所があるかもしれません。
その際はなるべく早く追記しますので、指摘など頂ければ幸いです。
宜しくお願い致します。

■実現したいこと

  GridPaneに、5×5の形でStackPaneを配置しています。
StackPaneをボタンのように使用し、クリックされたときに
「何行目の何列目がクリックされたのか」という情報をGridPaneが把握出来るようにしたいと考えています。
なるべくstatic修飾子を用いない方法で実現したいです。
因みに、ここでいうStackPaneとは、StackPaneを継承したクラス「Square.java」を指しています。

■試してみた解決策

1、Grid.java内にてEventを定義し、Squareクラスのインスタンス(squares)に実装
-> static修飾子を沢山使用する羽目になったので断念。
2、Observerパターンというものがあることを知ったので、Squareクラスを観察対象のクラスにする方法を考案
-> SquareクラスはStackPaneクラスを継承しているので断念。

■コード

クラス1 Grid.java

lang

1public class Grid extends Observable implements Initializable, Observable{ 2  public class Grid(){ 3 GridPane gp = new GridPane(); 4 private final Square[][] squares = new Square[5][5]; 5 for(int i=0;i<5;i++){ 6 for(int j=0;j<5;j++){ 7 squares[i][j] = new Square(); 8 // 何行目の何列目かを伝える 9 squares[i][j].where_I_am(i,j); 10 // GridPaneに配置 11 gp.add(squares[i][j],i,j); 12 ●●●修正●●● 13 squares[i][j].setOnMouseClicked(new EventHandler<MouseEvent>() { 14 @Override 15 public void handle(MouseEvent event) { 16 choosenRow = squares[i][j].gridPaneRow; 17 choosenColumn = squares[i][j].gridPaneColumn; 18 } 19 }); 20 ●●●ここまで●●● 21 } 22 } 23}

クラス2 Square.java extends StackPane

lang

1public class Square extends StackPane{ 2 private int gridPaneRow; 3 private int gridPaneColumn; 4 public void where_I_am(int row, int column){ 5 gridPaneRow = row; 6 gridPaneColumn = column; 7 } 8}

■よくわかっていない点

1、SquareクラスがStackPaneを継承する以外の方法があるかどうか
2、static修飾子を使わない方法自体が可能であるかどうか

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

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

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

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

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

guest

回答2

0

解決済みですけど、少し別の考え方もコメントしてみたいと思います。

特定のStackPaneがクリックされたときにStackPaneの「どの区画がクリックされたか」を知るために以下のようにも書けます。

Java

1public class Grid extends Observable implements Initializable, Observable{ 2 int choosenRow; 3 int choosenColumn; 4 5 public class Grid(){ 6 GridPane gp = new GridPane(); 7 private final Square[][] squares = new Square[5][5]; 8 for (int i = 0; i < 5; i++) { 9 for (int j = 0; j < 5; j++) { 10 // lambda式/内部クラスではfinalな変数しか参照できない。 11 // i, jはfinalではないので直接参照できない 12 // col, rowは事実上finalなので直接参照できる 13 int col = i; 14 int row = j; 15 Square sq = new Square(); 16 gp.add(sq, col, row); 17 sq.setOnMouseClicked(new EventHandler<>() { 18 @Override 19 public void handle(MouseEvent event) { 20 choosenRow = row; 21 choosenColumn = col; 22 } 23 }); 24 } 25 } 26 } 27}

(このコード例ではSqureを配列変数に覚えておく必要はないので元のコードにあった配列変数は除いています)

つまり、このような目的では「Square自身が属性を保持する必要は必ずしもない」のですね。特定のSqureインスタンスの位置を表すローカル変数row, colがあるとき、これらが「事実上のfinal変数」ならばsetOnClickで設定するハンドラー処理内部(無名クラスやラムダ式)から直接それらを参照できる点がポイントです。


ちなみにJava8以降は抽象メソッドが一つしかないインターフェースに対して無名クラスを用いるよりはラムダ式を用いた方がよいと思います。JavaFXはこれをかなり意識して設計されておりsetOnXxxハンドラーに指定するようなインターフェースは殆どがラムダ式を使えるようになってますので。

java

1// 無名クラスを用いた例 2 3 sq.setOnMouseClicked(new EventHandler<>() { 4 @Override 5 public void handle(MouseEvent event) { 6 choosenRow = row; 7 choosenColumn = col; 8 } 9 }); 10 11// ラムダ式を用いた例 12 13 sq.setOnMouseClicked(event -> { 14 choosenRow = row; 15 choosenColumn = col; 16 });

投稿2018/03/04 11:53

KSwordOfHaste

総合スコア18394

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

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

hilty8

2018/03/05 02:17

丁寧な回答ありがとうございます。参考にさせていただきます。 ・Squreを配列変数に覚えておく必要はない ・これらが「事実上のfinal変数」ならばsetOnClickで設定するハンドラー処理内部(無名クラスやラムダ式)から直接それらを参照できる ・抽象メソッドが一つしかないインターフェースに対して無名クラスを用いるよりはラムダ式を用いた方がよい など理解が浅い点を多数自覚できました。全ての内容がわかるわけではないですが、根気強く取り組みたいと思います。
hilty8

2018/03/05 02:19

差し支えなければ、以上のような情報をどのように調べればよいのか、教えていただけないでしょうか。 現在は、取り敢えずOracleのJava公式リファレンスを参照しています。
KSwordOfHaste

2018/03/05 02:43 編集

ラムダ式や無名クラスの本体から何がアクセスできるかといった内容はOracleのAPIリファレンスには載っていません。これが載っているのは「言語仕様書」ですが、それは言語を学ぼうとしている段階で参照するにはあまりに難解ですので、Java8の文法について載っているJavaの参考書とか「Java ラムダ式 無名クラス」といった関連キーワードで検索してヒットする解説記事などを参照するとよいと思います。 --- ネット上の解説もピンからキリまで色々です。特に個人が書いているブログの「仕様の切れ端的記事」などには「不正確」「不十分」なものも多いです。 個人的には例えば以下のようなサイトはお勧めできると思います。内容がかなり豊富かつわかりやすく詳細な解説が読めると思います。 http://www.ne.jp/asahi/hishidama/home/tech/java/
hilty8

2018/03/05 03:44

ありがとうございます。検索方法および提示して頂いた資料について、早速目を通してみます。
guest

0

ベストアンサー

public 修飾子をつければ他クラスから参照できるようになります

投稿2018/03/04 08:19

y_waiwai

総合スコア87774

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

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

hilty8

2018/03/04 09:05

すみません、自分は初歩的なところで躓いているのだと思うのですが、 SquareクラスのインスタンスにどのようなEventを定義すれば、Squareインスタンスが持つintの値を受け取れるのか、もう少し詳しく教えていただけないでしょうか。
y_waiwai

2018/03/04 09:13

public int gridPaneRow; public int gridPaneColumn; とすれば、他クラスから Square sq=new Square(); int row=sq.gridPaneRow; int clm=sq.gridPaneColumn; とできます
hilty8

2018/03/04 10:16

試してみた方法について、質問のコード部分を編集してみたのですが、 「内部クラスから参照されるローカル変数は、finalまたは事実上のfinalである必要があります」 とNetBeansに怒られました。 Eventを実装する際の、その内部の記述について、再度お力を貸して頂けないでしょうか。
y_waiwai

2018/03/04 10:33

private final Square[][] squares = new Square[5][5]; final がついているせいですね。このfinalを外してやってみましょう。 finalをつけなければならない、という場合は、gridPaneRow、gridPaneColumn の値を返すメソッドをSquerクラスに追加してそこから取得するようにすればいいです。というより、不用意に値の変更を許さないようにするために、そうするほうがいいですね
hilty8

2018/03/04 10:56

早速試してみます。 何度も丁寧に回答していただき、本当にありがとうございました。とても助かりました。
y_waiwai

2018/03/04 10:56

public class Square extends StackPane{ private int gridPaneRow; private int gridPaneColumn; public int GetRow() { return gridPaneRow; } public int GetColumn() { return gridPaneColumn; } } としておいて、 public void handle(MouseEvent event) { choosenRow = squares[i][j].GetRow(); choosenColumn = squares[i][j].GetColumn(); } #Javaはまだ勉強中なので、スカがあるかもw
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問