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

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

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

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

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

1回答

6606閲覧

javaFXによるボタンの押しわけ

sobue

総合スコア329

JavaFX

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

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2016/10/12 13:13

編集2016/10/13 03:15

java

1 2package games; 3 4import java.util.ArrayList; 5import java.util.List; 6 7import javafx.application.Application; 8import javafx.geometry.Insets; 9import javafx.scene.Scene; 10import javafx.scene.control.Button; 11import javafx.scene.layout.FlowPane; 12import javafx.stage.Stage; 13 14public class Games extends Application{ 15 16 @Override 17 public void start(Stage primaryStage) throws Exception { 18 // TODO 自動生成されたメソッド・スタブ 19 20 //フレームのプロパティの設定 21 primaryStage.setTitle("Games"); 22 primaryStage.setWidth(400); 23 primaryStage.setHeight(300); 24 25 Button btn[] = new Button[6]; 26 int i = 0; 27 for(String a: buttonNameList()){ 28 btn[i] = new Button(a); 29 btn[i].setPrefWidth(150); 30 i++; 31 } 32 33 FlowPane fp = new FlowPane(10,10); 34 fp.setPadding(new Insets(10,10,10,10)); 35 36 fp.getChildren().addAll(btn); 37 Scene scene = new Scene(fp); 38 39 primaryStage.setScene(scene); 40 //フレームの表示 41 primaryStage.show(); 42 43 btn[1].getOnMouseClicked(); 44 } 45 46 private List<String> buttonNameList() { 47 // TODO 自動生成されたメソッド・スタブ 48 List<String> list = new ArrayList<String>(); 49 50 list.add("フラッシュ暗算"); 51 list.add("ブロック崩し"); 52 list.add("テトリス"); 53 list.add("ピクロス"); 54 list.add("スペースインベーダー"); 55 list.add("リバーシ"); 56 57 return list; 58 } 59 public static void main(String[] args) { 60 // TODO 自動生成されたメソッド・スタブ 61 Application.launch(args); 62 } 63} 64

上記の状態でボタンを出力することはできたのですが、ボタンのイベントを実装するするときに
btn[1].setOnAction(null);
としなくてはならないため、見直しでどのボタンを押下されているかがわかりません。
うまく押し分けできる方法をご教示ください。

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

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

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

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

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

KSwordOfHaste

2016/10/13 02:56

本サイトにはJavaFXのタグもありますので、JavaとJavaFXの両方のタグをつけるとよいと思います。
guest

回答1

0

ベストアンサー

「全てのボタンに対して同じアクションハンドラーを設定した場合、アクションハンドラーでどのボタンが押されたかをどうやって判断するか」が質問の趣旨と仮定して考えますと・・・

イベントハンドラーにはEvent(の派生クラスのインスタンス)が引数に渡されます。一般にイベントの発生元オブジェクトがどれなのかをEvent#getSource()で知ることができるのですが、コントロールに対して何かのユーザー操作を行った場合のイベントでは操作対象のコントロールがイベントの発生元となります。よって例えばハンドラーの中で押されたボタンのonActionPropertyをnullに設定したいのであれば次のようにできます。

@Override public void start(...) { for (...) { ... btn[i].setOnAction(Games::commonButtonAction); } ... } ... // ボタンのアクションを処理するメソッドの中でイベント発生元のボタンを参照する static void commonButtonAction(ActionEvent ev) { Button actionSource = (Button)ev.getSource(); actionSource.setOnAction(null); ... }

ラムダ式や無名クラスなどを使って直接イベント処理を書く場合はEvent#getSource()をわざわざ使わずともその文脈から見えるfinalな変数を用いて次のようにも書けます。Event#getSource()でボタンが得られることは分かっていても迂遠に感じられますしキャストもできれば避けたいので、こちらのほうが少し好ましく感じます。

java

1for (String a : ...) { 2 btn[i] = new Button(a); 3 // lambda式の中ではfinalな変数しか参照できない(btn[i]とはかけない)ので別の変数btnxを用いる 4 Button btnx = btn[i]; 5 btnx.setOnAction(ev -> { 6 btnx.setOnAction(null); 7 ... 8 }); 9 ... 10 i++; 11}

(Java8前提の文法であるメソッド参照やラムダ式を用いていますのでもしJava7なら適宜読み替えてください。)

投稿2016/10/13 05:40

KSwordOfHaste

総合スコア18394

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

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

sobue

2016/10/13 23:12

提示して頂いた例だとどのボタンを押した時の処理かわかりづらいですよね?フラッシュ暗算ボタンを押したら…とかがわかるようにしたいです
KSwordOfHaste

2016/10/14 10:38 編集

確かにそうですね。質問の内容がわりと広い範囲になりそうだったのでまずは限定的な回答をしてみたのです。自分ならどうするかの例を挙げてみましょうか?=>追記:自分なら名前のリストからボタンを作って次に・・・とは考えずに、最初から各ゲームの違いをすべて面倒みるようなGameクラスを定義し、起動時に必要なだけGameインスタンスを作った後は全てそのインスタンスに独自の処理をやってもらう作りにします。具体例を挙げてしまうと元のコードとかなりかけはなれてしまうので言葉だけで説明してみました。
sobue

2016/10/19 15:12

僕は、全てを手動でボタンに名前をつけて各ゲームのクラスを作る方法は思いつきましたが…あまりスッキリしないですね…
KSwordOfHaste

2016/10/19 16:26

どこがすっきりしないかはコードをみないとはっきりコメントできませんが・・・それはともかく最初に指摘すべき点を忘れていたのでコメントします。名前のリストだけで初期化をやろうとしていることがすっきり書けない一因だと思います。不十分な情報(名前だけ)でボタンを作ろうとすれば必然的にコードはすっきりとしたものにはならないのでは?名前、実行すべきアクション等々必要な情報を与えて初期化するようにすれば普通にすっきりすると思います。例えばその情報を引数としてボタンを作るメソッドを用意してもいいですし。 interface GameAction { void start(); } Button createGameButton(String name, GameAction action) { ... } Container.getChildren().add( createGameButton("ゲーム1", ()->Game1()), createGameButton("ゲーム2", ()->Game2()), ...); ゲーム開始時に押されたボタンをdisableにする処理などはcreateGameButtonの中で特にややこしいこともせずに平易に実装できます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問