質問するログイン新規登録
JavaFX

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

Java

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

FXML

FXMLは、JavaFXに用意されているXMLベースのGUI記述言語です

Q&A

1回答

59閲覧

【javafxに関する疑問】FXML内において、オブジェクトのコントロール分割は可能か?

Fitz

総合スコア3

JavaFX

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

Java

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

FXML

FXMLは、JavaFXに用意されているXMLベースのGUI記述言語です

0グッド

0クリップ

投稿2025/10/08 13:23

0

0

実現したいこと

javafxにて、画面内の短形(以降操作キャラと呼びます)を動かし、中央にある枠に触れた時と、枠の内部に入った時にテキストが変化するコードを作成しました。
作成後、「オブジェクトコントロールを個別に設定出来たら、操作キャラは操作キャラのクラスに処理を格納でき、現在のコントロールクラスの可読性が上がるのでは?」と思いました。
そこで質問です。FXMLにおいて、コントロール設定されたFXMLの、特定のオブジェクトのコントロールを他クラスに譲渡するというのは可能なのでしょうか?

発生している問題・分からないこと

実現可能か分からない
・FXMLのオブジェクト(今回の場合は短形を)のコントロールを他のクラスに譲渡できるのか?
→Screen2に記述している、「private Rectangle shape1;//操作キャラ」に関連する移動制御の処理は個別に用意したり、中央枠等の操作キャラ以外を種類ごとに分けて機能を拡張していきたい。

該当のソースコード

java

1package application; 2 3import java.net.URL; 4import java.util.ResourceBundle; 5 6import javafx.animation.AnimationTimer; 7import javafx.beans.binding.BooleanBinding; 8import javafx.beans.property.BooleanProperty; 9import javafx.beans.property.SimpleBooleanProperty; 10import javafx.fxml.FXML; 11import javafx.fxml.Initializable; 12import javafx.geometry.Bounds; 13import javafx.scene.input.KeyCode; 14import javafx.scene.layout.AnchorPane; 15import javafx.scene.paint.Color; 16import javafx.scene.shape.Rectangle; 17import javafx.scene.text.Text; 18 19public class Screen2 implements Initializable{ 20 21 @FXML 22 private AnchorPane screen2;//画面 23 24 @FXML 25 private Rectangle boundary1;//境界(図形) 26 private Bounds boundboundary1;//境界の境界線 27 28 @FXML 29 private Rectangle shape1;//操作キャラ 30 private Bounds boundshape1;//操作キャラ境界線 31 32 boolean tutch = false; 33 boolean included= false; 34 35 36 @FXML 37 private Text text; 38 39 //キー押下変数 40 private BooleanProperty wPressed = new SimpleBooleanProperty(); 41 private BooleanProperty aPressed = new SimpleBooleanProperty(); 42 private BooleanProperty sPressed = new SimpleBooleanProperty(); 43 private BooleanProperty dPressed = new SimpleBooleanProperty(); 44 private BooleanProperty shiftPressed = new SimpleBooleanProperty(); 45 46 private BooleanBinding keyPressed = wPressed.or(aPressed).or(sPressed).or(dPressed).or(shiftPressed); 47 48 49 50 //移動速度 51 private int movementVariable = 2; 52 53 //スピードアップ 54 private int speedUp = 3; 55 56 //短形の高さ: 57 private double shape1Height; 58 59 AnimationTimer timer = new AnimationTimer() { 60 @Override 61 public void handle(long timestamp) { 62 63 boundshape1 = shape1.getBoundsInParent(); 64 boundboundary1 = boundary1.getBoundsInParent(); 65 contains(boundshape1,boundboundary1); 66 67 if(wPressed.get()) { 68 if(shiftPressed.get()) { 69 shape1.setLayoutY(shape1.getLayoutY() - (movementVariable + speedUp)); 70 71 } 72 shape1.setLayoutY(shape1.getLayoutY() - movementVariable); 73 74 } 75 76 if(sPressed.get()){ 77 if(shiftPressed.get()) { 78 shape1.setLayoutY(shape1.getLayoutY() + (movementVariable + speedUp)); 79 } 80 shape1.setLayoutY(shape1.getLayoutY() + movementVariable); 81 } 82 83 if(aPressed.get()){ 84 if(shiftPressed.get()) { 85 shape1.setLayoutX(shape1.getLayoutX() - (movementVariable + speedUp)); 86 } 87 shape1.setLayoutX(shape1.getLayoutX() - movementVariable); 88 } 89 90 if(dPressed.get()){ 91 if(shiftPressed.get()) { 92 shape1.setLayoutX(shape1.getLayoutX() + (movementVariable + speedUp)); 93 } 94 shape1.setLayoutX(shape1.getLayoutX() + movementVariable); 95 } 96 97 if(tutch == true) { 98 text.setText("当たっています。"); 99 text.setFill(Color.RED); 100 } 101 if(included == true){ 102 text.setText("内部に入っています。"); 103 text.setFill(Color.RED); 104 } 105 if(tutch != true && included != true) { 106 text.setText("何にも接触していません。"); 107 } 108 109 110 checkBorder(); 111 112 } 113 }; 114 115 116 @Override 117 public void initialize(URL url, ResourceBundle resourceBundle) { 118 //shape1X座標 119 shape1Height = shape1.getHeight(); 120 //shape1四隅 121 boundshape1 = shape1.getBoundsInParent(); 122 boundboundary1 = boundary1.getBoundsInParent(); 123 movementSetup(); 124 125 keyPressed.addListener(((observableValue, aBoolean, t1) -> { 126 if(!aBoolean){ 127 timer.start(); 128 } else { 129 timer.stop(); 130 } 131 })); 132 } 133 134 public void movementSetup(){ 135 screen2.setOnKeyPressed(e -> { 136 if(e.getCode() == KeyCode.W) { 137 wPressed.set(true); 138 } 139 140 if(e.getCode() == KeyCode.A) { 141 aPressed.set(true); 142 } 143 144 if(e.getCode() == KeyCode.S) { 145 sPressed.set(true); 146 } 147 148 if(e.getCode() == KeyCode.D) { 149 dPressed.set(true); 150 } 151 152 if(e.getCode() == KeyCode.SHIFT) { 153 shiftPressed.set(true); 154 } 155 156 }); 157 158 screen2.setOnKeyReleased(e ->{ 159 if(e.getCode() == KeyCode.W) { 160 wPressed.set(false); 161 } 162 163 if(e.getCode() == KeyCode.A) { 164 aPressed.set(false); 165 } 166 167 if(e.getCode() == KeyCode.S) { 168 sPressed.set(false); 169 } 170 171 if(e.getCode() == KeyCode.D) { 172 dPressed.set(false); 173 } 174 if(e.getCode() == KeyCode.SHIFT) { 175 shiftPressed.set(false); 176 } 177 }); 178 } 179 180 //当たり判定左がチェック対象、右があたる可能性のあるオブジェクト 181 public void contains(Bounds smallShape, Bounds largeShape) { 182 183 //接触判定 184 if ( smallShape.intersects(largeShape)) { 185 tutch = true; 186 }else { 187 tutch = false; 188 } 189 190 //内部判定 191 if(largeShape.getMinX() < smallShape.getMinX() && largeShape.getMinY() < smallShape.getMinY() && 192 largeShape.getMaxX() > smallShape.getMaxX() && largeShape.getMaxY() > smallShape.getMaxY()){ 193 included = true; 194 } 195 else { 196 included = false; 197 } 198 199 200 } 201 202 public void checkBorder() { 203 //上からwsad変数 204 double topbound = 0; 205 double bottombound = screen2.getHeight() - shape1Height; 206 double leftbound = 0; 207 double lightbound = screen2.getWidth() - shape1Height; 208 209 //w移動制御 210 if(shape1.getLayoutY() <= topbound) { 211 shape1.setLayoutY(topbound); 212 } 213 //s移動制御 214 if(shape1.getLayoutY() >= bottombound) { 215 shape1.setLayoutY(bottombound); 216 } 217 //a移動制御 218 if(shape1.getLayoutX() <= leftbound) { 219 shape1.setLayoutX(leftbound); 220 } 221 //d移動制御 222 if(shape1.getLayoutX() >= lightbound) { 223 shape1.setLayoutY(lightbound); 224 } 225 226 } 227 228 229}

FXML

1<?xml version="1.0" encoding="UTF-8"?> 2 3<?import javafx.scene.layout.AnchorPane?> 4<?import javafx.scene.shape.Rectangle?> 5<?import javafx.scene.text.Text?> 6 7<AnchorPane fx:id="screen2" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="500.0" prefWidth="1000.0" xmlns="http://javafx.com/javafx/24.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Screen2"> 8 <children> 9 <Rectangle fx:id="shape1" arcHeight="5.0" arcWidth="5.0" fill="#ff8c1f" height="100.0" layoutX="450.0" layoutY="400.0" stroke="BLACK" strokeType="INSIDE" width="100.0" /> 10 <Rectangle fx:id="boundary1" arcHeight="5.0" arcWidth="5.0" fill="TRANSPARENT" height="200.0" layoutX="400.0" layoutY="150.0" stroke="BLACK" strokeType="INSIDE" width="200.0" AnchorPane.bottomAnchor="150.0" AnchorPane.leftAnchor="400.0" AnchorPane.rightAnchor="400.0" AnchorPane.topAnchor="150.0" /> 11 <Text fx:id="text" layoutX="417.0" layoutY="63.0" strokeType="OUTSIDE" strokeWidth="0.0" wrappingWidth="166.80340576171875" /> 12 </children> 13</AnchorPane> 14

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

試してみたこと。
・操作キャラを別のFXMLに作成。Screen2.FXMLで呼び出し(include)、Screen2クラスの操作キャラの初期値設定箇所に割り込ませてみた。
→対象の短形でNullpoint発生

補足

特になし

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

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

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

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

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

guest

回答1

0

・FXMLのオブジェクト(今回の場合は短形を)のコントロールを他のクラスに譲渡できるのか?

fx:includeでできました^^
Scene Builder で他の FXML ファイルを埋め込む #Java - Qiita

ただ何をどう分けるのかは悩ましいですね...

  • 移動自体はShape1Controllerに任せた
  • 当たり判定等はScreen2Controller側で

xml:screen2.fxml

1<?xml version="1.0" encoding="UTF-8"?> 2 3<?import javafx.scene.layout.AnchorPane?> 4<?import javafx.scene.shape.Rectangle?> 5<?import javafx.scene.text.Text?> 6<AnchorPane fx:id="screen2" 7 prefHeight="500.0" prefWidth="1000.0" 8 xmlns:fx="http://javafx.com/fxml" fx:controller="application.Screen2Controller"> 9 <children> 10 <fx:include fx:id="shape1" source="shape1.fxml"/> 11 <Rectangle fx:id="boundary1" arcHeight="5.0" arcWidth="5.0" fill="TRANSPARENT" height="200.0" layoutX="400.0" 12 layoutY="150.0" stroke="BLACK" strokeType="INSIDE" width="200.0"/> 13 <Text fx:id="text" layoutX="417.0" layoutY="63.0" text="何にも接触していません。"/> 14 </children> 15</AnchorPane>

java:Screen2Controller.java

1package application; 2 3import javafx.fxml.FXML; 4import javafx.fxml.Initializable; 5import javafx.scene.input.KeyCode; 6import javafx.scene.layout.AnchorPane; 7import javafx.scene.shape.Rectangle; 8import javafx.scene.text.Text; 9 10import java.net.URL; 11import java.util.ResourceBundle; 12 13public class Screen2Controller implements Initializable { 14 @FXML private AnchorPane screen2; 15 @FXML private Rectangle boundary1; 16 @FXML private Rectangle shape1; 17 @FXML private Text text; 18// @FXML private Shape1Controller shape1Controller; // コントローラも取れる 19 20 @Override public void initialize(URL url, ResourceBundle resourceBundle) { 21 shape1.layoutXProperty().addListener((_, _, _) -> checkShape1()); 22 shape1.layoutYProperty().addListener((_, _, _) -> checkShape1()); 23 24 screen2.setOnKeyPressed(e -> { 25 if (e.getCode() == KeyCode.SPACE) { 26 shape1.setLayoutX(450); 27 shape1.setLayoutY(400); 28 } 29 }); 30 } 31 32 private void checkShape1() { 33 var boundshape1 = shape1.getBoundsInParent(); 34 var boundboundary1 = boundary1.getBoundsInParent(); 35 var included = boundboundary1.contains(boundshape1); 36 var touch = boundboundary1.intersects(boundshape1); 37 38 if (included) text.setText("内部に入っています。"); 39 else if (touch) text.setText("当たっています。"); 40 else text.setText("何にも接触していません。"); 41 42 var top = 0d; 43 var bottom = screen2.getHeight() - shape1.getHeight(); 44 var left = 0d; 45 var right = screen2.getWidth() - shape1.getWidth(); 46 47 if (shape1.getLayoutY() <= top) shape1.setLayoutY(top); 48 if (shape1.getLayoutY() >= bottom) shape1.setLayoutY(bottom); 49 if (shape1.getLayoutX() <= left) shape1.setLayoutX(left); 50 if (shape1.getLayoutX() >= right) shape1.setLayoutX(right); 51 } 52}

xml:shape1.fxml

1<?xml version="1.0" encoding="UTF-8"?> 2 3<?import javafx.scene.shape.Rectangle?> 4<Rectangle fx:id="shape1" arcHeight="5.0" arcWidth="5.0" fill="#ff8c1f" height="100.0" layoutX="450.0" layoutY="400.0" 5 focusTraversable="true" stroke="BLACK" strokeType="INSIDE" width="100.0" xmlns:fx="http://javafx.com/fxml" 6 fx:controller="application.Shape1Controller"/>

java:Shape1Controller.java

1package application; 2 3import javafx.animation.AnimationTimer; 4import javafx.beans.binding.BooleanBinding; 5import javafx.beans.property.BooleanProperty; 6import javafx.beans.property.SimpleBooleanProperty; 7import javafx.fxml.FXML; 8import javafx.fxml.Initializable; 9import javafx.scene.shape.Rectangle; 10 11import java.net.URL; 12import java.util.ResourceBundle; 13 14public class Shape1Controller implements Initializable { 15 @FXML private Rectangle shape1; 16 17 private final BooleanProperty wPressed = new SimpleBooleanProperty(); 18 private final BooleanProperty aPressed = new SimpleBooleanProperty(); 19 private final BooleanProperty sPressed = new SimpleBooleanProperty(); 20 private final BooleanProperty dPressed = new SimpleBooleanProperty(); 21 private final BooleanProperty shiftPressed = new SimpleBooleanProperty(); 22 private final BooleanBinding keyPressed = wPressed.or(aPressed).or(sPressed).or(dPressed).or(shiftPressed); 23 24 private final AnimationTimer timer = new AnimationTimer() { 25 @Override public void handle(long timestamp) { 26 var offset = shiftPressed.get() ? 5 : 2; 27 28 if (wPressed.get()) shape1.setLayoutY(shape1.getLayoutY() - offset); 29 if (sPressed.get()) shape1.setLayoutY(shape1.getLayoutY() + offset); 30 if (aPressed.get()) shape1.setLayoutX(shape1.getLayoutX() - offset); 31 if (dPressed.get()) shape1.setLayoutX(shape1.getLayoutX() + offset); 32 } 33 }; 34 35 @Override public void initialize(URL url, ResourceBundle resourceBundle) { 36 shape1.setOnKeyPressed(e -> { 37 switch (e.getCode()) { 38 case W -> wPressed.set(true); 39 case A -> aPressed.set(true); 40 case S -> sPressed.set(true); 41 case D -> dPressed.set(true); 42 case SHIFT -> shiftPressed.set(true); 43 } 44 }); 45 46 shape1.setOnKeyReleased(e -> { 47 switch (e.getCode()) { 48 case W -> wPressed.set(false); 49 case A -> aPressed.set(false); 50 case S -> sPressed.set(false); 51 case D -> dPressed.set(false); 52 case SHIFT -> shiftPressed.set(false); 53 } 54 }); 55 56 keyPressed.addListener(((_, aBoolean, _) -> { 57 if (!aBoolean) timer.start(); 58 else timer.stop(); 59 })); 60 } 61}

java:HelloApplication.java

1package application; 2 3import javafx.application.Application; 4import javafx.fxml.FXMLLoader; 5import javafx.scene.Scene; 6import javafx.stage.Stage; 7 8import java.io.IOException; 9 10public class HelloApplication extends Application { 11 public static void main(String[] args) { 12 launch(); 13 } 14 15 @Override public void start(Stage stage) throws IOException { 16 var fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("screen2.fxml")); 17 stage.setScene(new Scene(fxmlLoader.load())); 18 stage.show(); 19 } 20}

アプリ動画

投稿2025/10/08 21:56

TN8001

総合スコア10199

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

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

TN8001

2025/10/08 21:56

Rectangleを継承したクラスを作ったほうがシンプルな気もする^^;
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.30%

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

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

質問する

関連した質問