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

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

ただいまの
回答率

90.61%

  • Java

    13505questions

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

  • JavaFX

    394questions

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

javaFX tableViewのイベントハンドラについて

解決済

回答 1

投稿

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

noct

score 2

親ウィンドウの名前列のいずれかを選択してる状態でF3キーを入力後子ウィンドウが表示、その子ウィンドウのテキストフィールドに値を入力(文字列、数字何でも可)後OKボタンを押下すると子ウィンドウが閉じ、親ウィンドウの選択していたセルの表記がテキストフィールドで入力された値に切り替わる。というプログラムを作成中です。

package sample;

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.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.stage.Stage;

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 firstName;
@FXML private TableColumn<Person,String> lastName;
@FXML private TableColumn email;

@Override
public void initialize(URL location, ResourceBundle resources) {
//セルの編集を許可する処理(一先ず必要ないのでコメアウト)
//Callback<TableColumn<Person,String>,TableCell<Person,String>>
//lastNameFactory = TextFieldTableCell.forTableColumn();
//lastName.setCellFactory(lastNameFactory);

//単一セルの選択の有効化
tableView.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
tableView.getSelectionModel().setCellSelectionEnabled(true);

//名前列のデータ行のセルの配色変更(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().selectedItemProperty().addListener((ov,old,current)-> {
//どこが選択されてるか確認用出力
System.out.println( "選択セル(TableView)" );

//選択セルの取得処理
for (TablePosition pos : tableView.getSelectionModel().getSelectedCells()) {
//選択行、列の取得
int row = pos.getRow();
TableColumn lastName = pos.getTableColumn();

Person item = tableView.getItems().get(row);
String selected = (String) lastName.getCellObservableValue(item).getValue();
}
});
}
//キーイベント処理(F3) 名前カラム選択時
public void onGetfanc(KeyEvent keyEvent) throws IOException {

//Person.setLastName(lastName.getText());

tableView.setOnKeyPressed((KeyEvent event) ->{
if(event.getCode() == KeyCode.F3){
//if(se));

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();
}
}
//tableView.setItems(Person);
});
}
}

FXMLファイル

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.collections.FXCollections?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.cell.PropertyValueFactory?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import sample.Person?>
<?import java.net.URL?>
<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="名字">
<!-- 列ごとにセル・ファクトリを指定して、データを列に関連付ける -->
<cellValueFactory>
<!-- PropertyValueFactoryクラスを使用することでセル・ファクトリは実装 -->
<!-- Personクラスの対応するメソッドへの参照として表の列のプロパティを使用する -->
<PropertyValueFactory property="firstName" />
</cellValueFactory>
</TableColumn>
<TableColumn fx:id="lastName" text="名前">
<cellValueFactory>
<PropertyValueFactory property="lastName" />
</cellValueFactory>
</TableColumn>
<TableColumn text="メールアドレス">
<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>

```

試したこと

選択状態の検知をするバインディングは僕なりに記述をしてみたつもりです。
僕自身は後キータイプ処理のイベントハンドラをどうするか。という部分なのですが、列指定の情報を受取りイベントハンドラを起動する。というif文の記述方法が分かりません。説明下手で申し訳ないですが、ご教授して頂けたら幸いです。

補足情報(言語/FW/ツール等のバージョンなど)

より詳細な情報

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

キータイプ処理のイベントハンドラをどうするか

元のコードではStageを作成してFXMLLoaderでlastName.fxmlをロードして・・・という方法を想定しておられますが、単にTextInputDialogを用いた方が簡単です。元のコードのように自前でダイアログを実装するのでもよいのですが、モーダルにしたり、OKを押したかキャンセルしたかや、入力結果を得るためのインターフェースを設けたコントローラーを実装したりと若干面倒くさいことをしなければなりません。TextInputDialogを用いればそのような面倒なことをしなくてもshowAndWaitの戻り値をチェックすることで簡単にユーザー入力を実現できますので本回答ではTextInputDialogを用いた例としました。
ちなみにonKeyfancの中でsetOnKeyPressedを用いていますが、ここでハンドラーを登録するのは不適切(不要)と思います。以下の回答例を参照ください。

選択状態の検知をするバインディングは僕なりに記述をしてみたつもりです。

これは選択状態の変化を自前で監視している点を指していると思いますが、それは必要ないと思います。'F3'キー押下時のイベントハンドラーの方で、「lastNameが選択されているかどうか」をTableViewSelectionModelを通じて容易にチェックできますし、わざわざ選択状態の変更を監視する意義はなさそうです。

実装は概ね次のようになると思います。

@FXML
private void onGetFunc(KeyEvent event) {
  if (event.getCode() == KeyCode.F3) {
    editSelectedLastName();
  }
}

private void editSelectedLastName() {
  TableView.TableViewSelectionModel<Person> sm = tableView.getSelectionModel();
  int index = sm.getSelectedIndex();
  if (index == -1) {
    // 選択されているセルがなければ何もしない
    return;
  }
  if (!sm.isSelected(index, lastName)) {
    // 選択セルが名字でなければ何もしない
    return;
  }

  Person person = sm.getSelectedItem();
  TextInputDialog dialog = new TextInputDialog(person.getLastName());
  dialog.setTitle("名字入力画面");
  Optional<String> result = dialog.showAndWait();
  if (result.isPresent()) {
    person.setLastName(result.get().trim());
  }
}

なお・・・

  • GetKeyfanc
    FXML上でonKeyPressedのハンドラーとしてこのメソッドが定義されてますが、メソッドのシグナチャーが@FXMLなしのpublicになっています。回答コードではおそらく一般的な定義方法と思えるので@FXMLありのprivateとしています。またメソッド名はtypoのような気がしたので、GetKeyFuncという名称に変えています。FXML上のハンドラー定義がonKeyPressed="#onGetFunc"となっている前提です。

  • 名前と名字

親ウィンドウの名前列のいずれかを選択してる状態でF3キーを入力後

元のFXML定義をみると「名前=lastName、名字=firstName」になっていますが本来は逆ですね?回答コードでは「lastName=名字」とし、ダイアログのタイトルを「名字入力画面」としています。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/09/26 15:48

    親切な回答有難う御座います。
    TextInputDialogを利用すれば簡単に実装出来るという事知れました。
    僕自身簡単な処理方法というよりオブジェクト指向の概念も交えて処理出来たらなと考えていたのであの様な方法を使っていたのですが、ここまで簡単に実装が出来るとなるとオブジェクトに拘らない方が簡潔になりますね。
    一つの事に拘らず幅広く組み立てられるようにしていきたいと思います。
    有難う御座いました。

    キャンセル

  • 2017/09/26 17:16

    > 簡単な処理方法というよりオブジェクト指向の概念も交えて処理出来たらなと考えていた

    自前でStage+FXMLで実装するかTextInputDialogを用いるかについては、オブジェクト指向あるいはJavaFXの練習として前者で実装してみるというのは無駄ではないと思います。実際TextInputDialogを利用可能なのはごく単純な入力でよい場合だけであり、多少なりとも複雑なダイアログにしたい場合はDialog/DialogPaneあるいはStage+FXMLによる実装が必要になります。

    最初はなるべく単純な機能にし、できあいのクラスをうまく利用しつつ、JavaFXに慣れていくにつれてより複雑で応用的な実装に挑戦してみるとよいかも知れません。例えばTextInputDialogと同様のものを自前で実装してみるとJavaFXの仕組みを知る上でも有効な練習になると思います。

    キャンセル

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

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

関連した質問

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

  • Java

    13505questions

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

  • JavaFX

    394questions

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