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

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

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

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

Java

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

Q&A

解決済

1回答

1390閲覧

javaFX TableView セルの値更新

noct

総合スコア8

JavaFX

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

Java

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

0グッド

0クリップ

投稿2017/09/28 02:46

###前提・実現したいこと
別ウィンドウで入力された値を親ウィンドウ側のセルに表示
lastName.fxmに入力後→Okボタン→Person.fxmlの指定のセルの値変更

###該当のソースコード
Person.java

package sample; import javafx.beans.property.SimpleStringProperty; public class Person { private SimpleStringProperty firstName = new SimpleStringProperty(""); private SimpleStringProperty lastName = new SimpleStringProperty(""); private SimpleStringProperty email = new SimpleStringProperty(""); public Person() { this("", "", ""); } public Person(String firstName, String lastName, String email) { setFirstName(firstName); setLastName(lastName); setEmail(email); } public String getFirstName() { return firstName.get(); } public void setFirstName(String _firstName) { firstName.set(_firstName); } public String getLastName() { return lastName.get(); } public void setLastName(String _lastName) { lastName.set(_lastName); } public String getEmail() { return email.get(); } public void setEmail(String _email) { email.set(_email); } } ```Controller.java

package sample;

import javafx.collections.ListChangeListener;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;
import javafx.util.Callback;

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;

public class Controller implements Initializable{

@FXML private TableView<Person> tableView; @FXML private TableColumn<Person,String> firstName; @FXML private TableColumn<Person,String> lastName; @FXML private TableColumn<Person,String> email; @Override public void initialize(URL location, ResourceBundle resources) { //単一セルの選択の有効化 tableView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); tableView.getSelectionModel().setCellSelectionEnabled(true); //セルの編集を許可する処理 tableView.setEditable(true); lastName.setEditable(true); Callback<TableColumn<Person,String>,TableCell<Person,String>> lastNameFactory = TextFieldTableCell.forTableColumn(); lastName.setCellFactory(lastNameFactory); //編集完了後の更新処理 lastName.setOnEditCommit((TableColumn.CellEditEvent<Person,String>event)->{ Person person = event.getTableView().getItems().get(event.getTablePosition().getRow()); person.setLastName(event.getNewValue()); }); //名前列のデータ行のセルの配色変更(sample.css) lastName.setCellFactory(TableColumn -> new TableCell<Person, String>(){ //セルに変更があった場合呼ばれるupdateItemメソッドを利用する public void updateItem(String item,boolean empty){ super.updateItem(item,empty); if(empty || item == null){ setText(null); setGraphic(null); }else{ setText(item); getStyleClass().add("tableCellClass"); } } }); //選択状態を検知するバインディングの設定 tableView.getSelectionModel().getSelectedCells().addListener((ListChangeListener.Change<? extends TablePosition> c) -> { //選択セルの取得処理 for (TablePosition pos : tableView.getSelectionModel().getSelectedCells()) { //選択行、列の取得 int row = pos.getRow(); int col = pos.getColumn(); //取得した行、列をセット ControllersCommon.setRow(row); ControllersCommon.setCol(col); //行、列の取得情報をもとにカラムの情報を取得 TableColumn<Person,String> tableColumn = pos.getTableColumn(); //選択行の取得 Person item = tableView.getItems().get(row); //選択行のカラムデータをdispLastNameとして取得 String dispLastName = tableColumn.getCellObservableValue(item).getValue(); //確認用println System.out.println( "選択セル(TableView)" + dispLastName); //dispLastNameを名前列にセット ControllersCommon.setLastName(String.valueOf(dispLastName)); } }); } //キーイベント処理(F3) 名前カラム選択時 @FXML public void onGetFanc(KeyEvent keyEvent) throws IOException { //選択されていた場合のキータイプイベントハンドラ処理 tableView.setOnKeyReleased((KeyEvent event) -> { //名前列が選択されてる場合の条件分岐 if(ControllersCommon.getCol() == 1) { if (event.getCode() == KeyCode.F3) { try { Stage stage = new Stage(); Parent root = FXMLLoader.load(getClass().getResource("lastName.fxml")); Scene scene = new Scene(root); stage.setScene(scene); stage.setTitle("名前入力画面"); stage.showAndWait(); } catch (IOException e) { e.printStackTrace(); } } } }); }

}

person.fxml

1
<?xml version="1.0" encoding="UTF-8"?> <?import java.net.URL?> <?import javafx.collections.FXCollections?> <?import javafx.geometry.Insets?> <?import javafx.scene.control.Label?> <?import javafx.scene.control.TableColumn?> <?import javafx.scene.control.TableView?> <?import javafx.scene.control.cell.PropertyValueFactory?> <?import javafx.scene.layout.ColumnConstraints?> <?import javafx.scene.layout.GridPane?> <?import javafx.scene.layout.RowConstraints?> <?import sample.Person?> <GridPane alignment="center" hgap="10" vgap="10" xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller"> <padding> <Insets bottom="10.0" left="10.0" right="10.0" top="10.0" /> </padding> <Label style="-fx-font:NORMAL 20 Tahoma;" text="アドレス帳" GridPane.columnIndex="0" GridPane.rowIndex="0"> </Label> <TableView fx:id="tableView" editable="true" onKeyPressed="#onGetFanc" GridPane.columnIndex="0" GridPane.rowIndex="1"> <columns> <!-- TableCollumクラスを利用して、データを表示する為の列を追加 --> <TableColumn text="名字" editable="true"> <!-- 列ごとにセル・ファクトリを指定して、データを列に関連付ける --> <cellValueFactory> <!-- PropertyValueFactoryクラスを使用することでセル・ファクトリは実装 --> <!-- Personクラスの対応するメソッドへの参照として表の列のプロパティを使用する --> <PropertyValueFactory property="firstName" /> </cellValueFactory> </TableColumn> <TableColumn fx:id="lastName" text="名前" editable="true"> <cellValueFactory> <PropertyValueFactory property="lastName" /> </cellValueFactory> </TableColumn> <TableColumn text="メールアドレス" editable="true"> <cellValueFactory> <PropertyValueFactory property="email"/> </cellValueFactory> </TableColumn> </columns> <items> <!-- データの行を定義して、そのデータを表の列に関連付ける --> <FXCollections fx:factory="observableArrayList"> <Person firstName="Jacob" lastName="aa" email="aaaa.aa@aaaa.aa"/> <Person firstName="Isabella" lastName="bb" email="bbbb.bb@bbbb.bb"/> <Person firstName="Ethan" lastName="cc" email="cccc.cc@cccc.cc"/> <Person firstName="Michael" lastName="dd" email="dddd.dd@dddd.dd"/> </FXCollections> </items> </TableView>
<stylesheets> <URL value="@sample.css" /> </stylesheets>
<columnConstraints> <ColumnConstraints /> </columnConstraints> <rowConstraints> <RowConstraints /> <RowConstraints /> </rowConstraints> </GridPane>
###補足情報 TextInputDialogを利用した方が簡単という意見も聞いてるのですが、 オブジェクト思考を理解しながらのプログラム作成をしようと思っています。 効率等かなり悪いのは承知ですが、javaの勉強という観点で見て頂けると嬉しいです。

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

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

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

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

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

guest

回答1

0

ベストアンサー

最初に質問のしかたについて・・・

質問文には具体的な問題点(困っている点、わからない点)が書かれてません。「どうやって入力ダイアログを実現すればよいか」を勉強したい、あるいはどうやるべきかよくわからないといったことが問題なのであろうとは思いますが、それは漠然としすぎているため短く端的なアドバイスを回答できません。

このようなものは本サイトで期待されるいわゆる「質問」とはなっておらず、解説・指導を期待するような「指導依頼」というべきものになってしまいます。指導依頼はQ&Aサイトにするのではなく学校の先生などの「指導者」に対してすべきものです。

teratail: 質問するときのヒント

ちなみにControllersCommonクラスのソースがないので、例え閲覧者がソースコードをコピペしても、どんな問題であるかを推測するために簡単にプログラムを動かてみることができません。また前回の質問からの続きのためか元の質問にあったソースを省略しておられますが、閲覧者にとって前回の質問の内容を見ないと全容がわからないような質問の仕方はいただけません。最小限前回の質問へのリンクを書いて「これこれのソースはこちらの質問をごらんください」といった補足をしておかないと一般の閲覧者にはチンプンカンプンな内容になってしまいますよ?


さてプログラムの設計についてですが・・・

ダイアログを自前で実装するのであれば、JavaFXにおけるFXMLLoaderとルートノードとコントローラーの使い方について把握する必要があります。まずダイアログ用に別途コントローラークラスを定義しなければなりません。そして、主画面のコントローラー(Controllerクラス)のインスタンスとダイアログのコントローラーインスタンスの間で情報をやりとりするような設計にすべきです。ご質問のコードではControllersCommonクラス(staticインターフェースしか備えていないので要するに単なるグローバル変数置き場)が使われてますが、こうしたクラスは(オブジェクト指向云々のレベルではなく、そもそもモジュール設計の観点から)用いるべきではありません。

とりあえずヒントをいうと、

  • ダイアログ用にコントローラークラスを定義する

コントローラークラスは別途定義する必要があります。publicクラスにするのが分かり易いでしょう。仮にこのクラスをDialogControllerとしておきましょう。ダイアログでOKが押されたかCancelが押されたかやユーザが入力した文字列はこのコントローラークラス(のインスタンス)が管理すべきです。

  • ダイアログのコントローラークラスを取り出す方法を知る

ダイアログのFXMLファイルをloadした後で、FXMLLoader#getControllerを使ってください。FXMLLoderが自動的に生成したDialogControllerのインスタンスを取り出すことができます。具体的には次のようにします。

java

1FXMLLoader loader = new FXMLLoader(getClass().getResource("...")); 2Parent root = loader.load(); 3DialogController dialogController = loader.getController(); 4...
  • ダイアログと主画面とのやりとり

Controller#onGetFuncの中でDialogControllerのインスタンスメソッド(staticでないメソッド)を通じて情報のやりとり(OKが押されたかどうかや入力結果の文字列を取り出したり)といったことをしてください。

  • ダイアログのモダリティ

Stage#initModalityを用います。モーダルを推奨する理由はダイアログ表示開始時に「TableViewのどのセルが選択中か」を調べればダイアログ表示中に選択位置が変化する可能性を考慮する必要がなくなり、UIの仕様(ひいては設計や実装)がより単純になるからです。前回の回答で、「選択状態を検知するバインディングの設定」は不要に思えるとコメントしましたが、これはモーダルにすることを想定していたのです。

投稿2017/09/28 07:39

KSwordOfHaste

総合スコア18392

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

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

noct

2017/09/28 08:11

前回に引き続き回答有難う御座います。 また、質問の仕方、内容、配慮など全てにおいて足りていなかった事お詫び致します。 足らないソースコード等初めは載せようと思ったのですが、文字数制限に引っ掛かってしまいやむを得ず消す形となってしまいました。 回答者様にとって必要な情報が記述されてるクラスを消すという無知にも程がある考え方反省しております。 確かに僕自身、質問。というより指導、解答を求めてるものでした。 場をわきまえない発言等お許し下さい。今後気を付けます。 アドバイスも頂けて光栄です。有難う御座います。 まずそもそもの部分が理解し切れていない、いきなり飛ばしすぎな事をしてしまってる。という事ですね…。javaFXというよりjava自体1週間程度の学習期間でしたので勉強すべき順番等間違いだらけだという事に気づきました。 モーグルの利用等、方法を変え勉強の方進めたいと思います。 親切な解答本当に有難う御座います。以後質問の仕方等には注意したいと思います。
KSwordOfHaste

2017/09/28 08:47 編集

Javaを始めて1週間でここまで来たのなら「すごい!」という印象です・・・GUIプログラムはそもそも難易度は高めなので、(少なくとも自分などよりは)ずっと早く理解できるようになるんじゃないでしょうか。頑張ってください。
noct

2017/09/28 09:41

有難う御座います。知ったかぶりをしてるだけの無知な愚か者です… javaFXを初めたのもjavaよりGUIを直接意識しながらプログラミングが出来る。という適当な考えで手を出してしまっただけの事であって、これがやりたい。あれがやりたい。等明確な目標も目的もまだありません(汗) いずれゲームの様なものを作れる様になれれば。とは思ってますが、このままでは何年先になるのやら……。 難易度高め。という言葉を聞けてやる気が湧きました。 無茶な事はせず着実に確実なソースコードを記述していける様努力したいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問