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

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

ただいまの
回答率

90.47%

  • Java

    14101questions

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

  • JavaFX

    402questions

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

javaFX TableView セルの値更新

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 868

noct

score 2

前提・実現したいこと

別ウィンドウで入力された値を親ウィンドウ側のセルに表示
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

<?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の勉強という観点で見て頂けると嬉しいです。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

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

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

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

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

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


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

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

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

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

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

FXMLLoader loader = new FXMLLoader(getClass().getResource("..."));
Parent root = loader.load();
DialogController dialogController = loader.getController();
...
  • ダイアログと主画面とのやりとり
    Controller#onGetFuncの中でDialogControllerのインスタンスメソッド(staticでないメソッド)を通じて情報のやりとり(OKが押されたかどうかや入力結果の文字列を取り出したり)といったことをしてください。

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/28 17:11

    前回に引き続き回答有難う御座います。
    また、質問の仕方、内容、配慮など全てにおいて足りていなかった事お詫び致します。
    足らないソースコード等初めは載せようと思ったのですが、文字数制限に引っ掛かってしまいやむを得ず消す形となってしまいました。
    回答者様にとって必要な情報が記述されてるクラスを消すという無知にも程がある考え方反省しております。

    確かに僕自身、質問。というより指導、解答を求めてるものでした。
    場をわきまえない発言等お許し下さい。今後気を付けます。

    アドバイスも頂けて光栄です。有難う御座います。
    まずそもそもの部分が理解し切れていない、いきなり飛ばしすぎな事をしてしまってる。という事ですね…。javaFXというよりjava自体1週間程度の学習期間でしたので勉強すべき順番等間違いだらけだという事に気づきました。
    モーグルの利用等、方法を変え勉強の方進めたいと思います。
    親切な解答本当に有難う御座います。以後質問の仕方等には注意したいと思います。

    キャンセル

  • 2017/09/28 17:47 編集

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

    キャンセル

  • 2017/09/28 18:41

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

    難易度高め。という言葉を聞けてやる気が湧きました。
    無茶な事はせず着実に確実なソースコードを記述していける様努力したいと思います。

    キャンセル

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

  • ただいまの回答率 90.47%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Java

    14101questions

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

  • JavaFX

    402questions

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