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

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

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

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

1749閲覧

nashorn + JavaFX + TableView で エラー発生

TasogareKK

総合スコア12

JavaFX

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2017/03/09 05:29

編集2017/03/10 00:14

先日コチラでお教えいただき TableViewにデータを表示させる事ができましたが
セル移動で エラー発生します。ただ エラー発生後も操作はできるのですが。
コレの対応について お教え願います。

『追記』ココカラ 2017/03/10 09:05

曖昧情報で失礼いたしました。
実は エラー発生の規則性を 見出す事はできませんでした。
現在分かっている事は 以下です。

  • 行や列は どこでも発生すると 思われる
  • 10回目位の移動時に 発生する事が多い
  • 起動直後の数回(キー&マウス)は 発生した事がない
  • カーソルキーで高速移動(左右上下)すると 発生頻度は高い
  • マウスで隣接しないセルに移動させると 発生頻度は高い
  • エラー発生後 引続き各種セル移動をした場合 再発頻度は低い
  • Shift , Ctrl キー の 依存性は おそらく無いと思われる

『追記』ココマデ

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at javafx.scene.control.TableView$TableViewArrayListSelectionModel.handl
eSelectedCellsListChangeEvent(TableView.java:3054)
at javafx.scene.control.TableView$TableViewArrayListSelectionModel.clear
AndSelect(TableView.java:2423)
以下略(約60行)

この問題を解決できても 実装させたい機能はまだまだたくさんあり
JavaScriptで 書いていくには 難問続きになる事が予想されます。
例えば 次に着手予定のTextField埋め込み とか。

この際だから TableView周辺を Javaで書き jarに仕上げて
jjsを -cpオプションで コールする という手段も考えられます。( 各アプリは nashornで )
その方が得策なら 10数年ぶりに Javaを書くのもアリかなと思っていますが
すっかり忘れた言語ですので 旨くいかないと時間の無駄使いになりかねません。
ついでに この辺りのご助言も 頂けたら幸いです。

★★ 起動コマンド
"C:\Program Files\Java\jre1.8.0_121\bin\jjs.exe" -fx ./1000.js

FXML

1<?xml version="1.0" encoding="UTF-8"?> 2<?import javafx.scene.control.TableView?> 3<?import javafx.scene.layout.VBox?> 4<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1"> 5 <children> 6 <TableView id="TB0000" fx:id="TB0000" prefHeight="200.0" prefWidth="200.0" /> 7 </children> 8</VBox>

javascript

1//============================================================================== 2var File = Java.type('java.io.File'); 3var FXMLLoader = Java.type('javafx.fxml.FXMLLoader'); 4var ComboBoxTableCell = Java.type('javafx.scene.control.cell.ComboBoxTableCell'); 5load('fx:base.js'); 6load('fx:fxml.js'); 7load('fx:controls.js'); 8var TB0000,Col000; 9//============================================================================== 10function file2URL(file){return new File(file).toURI().toURL();} 11//============================================================================== 12function start(stage){ 13 //-------------------------------------------- 14 var fxml = './1000.fxml'; 15 var root = FXMLLoader.load(file2URL(fxml)); 16 //-------------------------------------------- 17 TB0000 = root.lookup('#TB0000'); 18 //-------------------------------------------- 19 var Cds000 = [ 20 {'id':"CODE",'tx':"コード",'wd': 90,'ag':"CC",'inp':"V",'fw':"N",'bC':"240,240,240",'fC':" 30, 40, 50",'tp':'S','defV':'Z_9999'}, 21 {'id':"NAME",'tx':"名前", 'wd':120,'ag':"CL",'inp':"T",'fw':"N",'bC':"240,255,255",'fC':" 30, 40,120",'tp':'S','defV':'X'}, 22 {'id':"BRTH",'tx':"誕生日",'wd':108,'ag':"CC",'inp':"V",'fw':"N",'bC':"255,255,255",'fC':"180, 80,100",'tp':'D','defV':'X'}, 23 {'id':"AGES",'tx':"年齢", 'wd': 60,'ag':"CR",'inp':"V",'fw':"B",'bC':"255,255,255",'fC':" 0,100,180",'tp':'I','defV':'0'} 24 ]; // Column.Design 25 //-------------------------------------------- 26 var Dat000 = [ 27 ['A_1234','Tasogare','1980/01/01','36'], 28 ['B_5678','ほげ太郎','2010/01/01'] // 最終フィールド欠落 29 ]; // ソースは CSV.load や SQL.結果set の 予定故 文字列の2次元配列を 準備 30 //-------------------------------------------- 31 Col000 = setTBL(TB0000,Cds000,Dat000); 32 //-------------------------------------------- 33 stage.title = 'TEST'; 34 stage.setScene(new Scene(root)); 35 stage.show(); 36 //-------------------------------------------- 37 // toDo = 入力IF(Text,Combo),入力完了イベント,行内自動演算,err.Check,,,,,,集計行,新規行,行並替 38} 39//============================================================================== 40//ココから下は libTBL.js として 独立させる予定 41//============================================================================== 42var FXCollections = Java.type('javafx.collections.FXCollections') 43var aryAlg = []; 44 aryAlg['CC'] = 'CENTER;'; 45 aryAlg['CL'] = 'CENTER-LEFT;'; 46 aryAlg['CR'] = 'CENTER-RIGHT;'; 47var aryFnW = []; 48 aryFnW['N'] = 'normal;'; 49 aryFnW['B'] = 'bold;'; 50// 型(tp) = [ S(string) D(date/time) I(int) R(real) ] 51// 入力(in) = [ V(view) T(TextField) C(ComboBox) ] 52//============================================================================== 53function setTBL(TBL,aryCds,aryDat){ 54 //-------------------------------------------- 55 TBL.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); 56 TBL.getSelectionModel().setCellSelectionEnabled(true); 57 TBL.setStyle("-fx-font-family:'Courier New',monospace;"); 58 TBL.setStyle("-fx-font-size:14;"); 59 TBL.setEditable(true); 60 //-------------------------------------------- 61 // column 62 var aryCol = []; 63 for(var cc=0;cc<aryCds.length;cc++){ 64 //------------------ 65 var _Cds = aryCds[cc]; 66 //------------------ 67 var styC = ''; 68 styC += '-fx-padding:2px 4px;'; // padding 69 styC += '-fx-alignment:' + aryAlg[_Cds.ag]; // alignment 70 styC += '-fx-font-weight:' + aryFnW[_Cds.fw] ; // フォント.weight 71 styC += '-fx-text-fill: rgb(' + _Cds.fC + ');'; // 前景色 72 //------------------ 73 var tCol = new TableColumn(_Cds.tx); // text 74 tCol.id = _Cds.id; // id (不要?) 75 tCol.prefWidth = _Cds.wd; // 幅 76 tCol.setStyle(styC); // スタイル 77 valFac(tCol,_Cds.inp,_Cds.tx); // cellValueFactory 78 //------------------ 79 TBL.getColumns().add(tCol); 80 aryCol.push(tCol); 81 //------------------ 82 } 83 //-------------------------------------------- 84 // data 85 var objDat = []; 86 for(var c0=0;c0<aryDat.length;c0++){ 87 var ob = {}; 88 for(var c1=0;c1<aryCds.length;c1++){ 89 if(aryDat[c0].length>c1){ 90 ob[aryCds[c1].tx] = aryDat[c0][c1]; 91 }else{ 92 ob[aryCds[c1].tx] = aryCds[c1].defV; 93 } 94 } 95 objDat.push(ob); 96 } 97 TBL.setItems(FXCollections.observableList(objDat)); 98 //-------------------------------------------- 99 return aryCol; 100 //-------------------------------------------- 101} 102//============================================================================== 103function valFac(tCol,inp,tx){ 104 if(inp=='V'){ 105 tCol.cellValueFactory = function(p){ 106 var x = p.getValue()[tx]; 107 return new ReadOnlyObjectWrapper(x); 108 } 109 } 110 if(inp=='T'){ 111 //tCol.cellValueFactory = ( /* TextField */ ); 112 } 113} 114//============================================================================== 115

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

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

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

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

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

KSwordOfHaste

2017/03/09 23:44

「セル移動でエラー発生」では曖昧です。スタックトレースからセルの選択操作で例外が発生していることが伺えますが、再現するための操作手順を正確かつ具体的に記載した方がよさそうです。例えば「起動直後にコードの1行目でマウスボタンを左クリック、次に同じ列の2行目をShift+左クリック、次に・・・」という具合に。
guest

回答1

0

ベストアンサー

残念ながら再現できなかったです。

なお、推測で恐縮ですが原因に心当たりがあるのでコメントします。間違ってるかもしれないのでそこはご容赦を。

自分の推測はJDK8でのJavaFXのバグではないかと思います。

JavaFXのListViewやTableViewに用いられているMultiSelectionModelの実装クラスMultipleSelectionModelBaseにはバグがありまして「どの位置の選択状態が変化したか」のインデックスの情報が不正になる場合があります。そのようなケースではListChangeListener.Changeに対してgetRemovedやgetAddedSubListを呼び出すと例外(IndexOutOfBoundsなど)が発生します。
本件の例外発生個所の数行前(3046行目)でgetRemovedを呼び出してますのでおそらくはこのバグの影響で不正なインデックスにより選択解除アイテムを求めたためNPEが発生していると思いました。

OracleへのバグレポートJDK-8165222の状況をみるとJDK8u60以降にバグが作りこまれたこととJDK9では発生しないことが分かっています。

レポート時期は昨年8月ですが現在に至るまでJDK8では対策されてません。担当の言を自分なりに解釈すると「JDK9では大規模なリファクタリングによりこのバグは治った。JDK8に本件だけ対策するのは可能だけどデグレードしないためにはちゃんとテストしなきゃいけない(のですぐに入れるのは厳しいかな…)」みたいな感じでしょうか

This is fixed in JDK 9 through a large amount of refactoring work. Backporting just this fix would be possible, but also most probably substantial work to identify the right (and minimal) change, as well as testing to avoid other regressions (fortunately selection is quite well tested).

対処:

  • SelectionMode.SINGLEを用いる

上に述べたバグは「SelectionMode.MULTIPLE」の場合のみ発生すると自分は考えています。またJDK8では本件はすぐに対策されない気がしてます。そこでもしSelectionMode.SINGLEが許容できるなら回避策になると思います。

  • JDK9を用いる

JDK9では多分発生しないと思います。まだ正式リリースされてないのでこの選択はイマイチですが。


追記:

TableView周辺を Javaで書き...

自分はJavascriptには暗くjjsも本質問で初めて知った程度なので以下は話半分くらいに聞いてください。

まずJava(JavaFXも)がボイラープレート的コードが多くなりがちなのでJavascriptでさらさら書けたらさぞうれしかろうと思いました。自分はjavascriptをさらさら書けないのですが、お見受けしたところ質問者さんは苦もなく書いておられるような…

悩ましいのはコントローラーをスッキリ書くためにはデータクラスにJavaFXプロパティーを実装しておきたい点なのですが、これはJavaでしかできそうもなく(?)かつJavaFXプロパティーがボイラープレートそのものなのがイケテないです。(lombokで@FXPropertyアノテーションを作ったらいいというような話を聞いたことがありますがあまり出回ってない(立ち消え?)感じなので残念ながら自分は試したことありません。)

あるいはデータクラスだけ我慢してJava側でJavaFXボイラープレートでクラス定義すればかなり気持ちよく作れるのかも知れません。例えば前回の質問にあったPropertyValueFactoryが使えるようになり、編集可能とするための実装はeditableプロパティーを(SceneBuilderで)trueにしてやるだけで済みます(=>間違い※1)。(質問者さんはTableCellが編集状態になったときTextFieldを置くといった制御を考えておられるようですがその実装が不要になります)

※1 訂正:「editableをtrueにしただけで済む」は間違いでした。
デフォルトのTableCellでは編集能力を持ってないので編集能力を持ったTableCellの派生クラスを用いないといけませんでした。訂正してお詫びします。なお編集対象がJavaFXプロパティーなら、TextFieldTableCellなどの提供クラスで簡単に実装できるため、やはりJavaFXプロパティーをデータクラスに実装した方が楽だとは思います。

余談ですがcssはJavascriptやJava上で書く必要はなく、cssファイルを定義しておき、FXMLでノードにくっつけてあげるほうが楽な気がします。(SceneBuilderでcssをrootノードにくっつけておけます)

取り留めないコメントで失礼しました。

投稿2017/03/10 03:11

編集2017/03/12 02:50
KSwordOfHaste

総合スコア18392

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

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

TasogareKK

2017/03/10 14:07

ご回答 ありがとうございます。 SelectionMode.SINGLEに変えても 頻度は減りましたが エラー発生しました。 Java9は 色々事情もありすぐには対応できません。 私のやりたい事の最終形は 例えば 注文appを作ろうとした時 1.TableViewとButtonを JavaFXで用意 2.SQLを用意  select 品番,単価,単位,0,0 from T  (0のフィールドは 数量,金額) 3.columnの属性を定義  ex. 数量は入力可で他は不可    数量が単位の整数倍でなければエラー    数量が入力されたら金額は自動計算 4.Buttonクリック時のfunctionを作る 5.TableViewに データとデザインを渡す .. で完了 としたい訳です。( コレは JavaScript で やりたい ) 私の意図する TableViewの拡張クラス(もどき)は JavaScriptがキツければ javaやむなしと思っています。 ただ Javaは私 ほぼ初心者なので なかなか踏ん切りがつかないのが実情です。 ご提案いただいた CSSですが 特にこだわりもありませんので 楽な方を選びたいと思います。 たくさんアドバイスいただきましたが しばらく考えてから結論を出す事にします。
KSwordOfHaste

2017/03/10 14:23

SINGLEに変えてもダメでしたか・・・ということは自分の予想は外れかも知れません。 (自分には質問者さんのコードに問題があるように見えないのです。) なお、目指すアプリの程度であればあえてJavaでデータクラスを作る必要性もないような気がしました。つまりJavascriptで作っても充分な気がします。ただJava側で問題が起こったときJavaのデバッグができないと問題の解決に時間がかかりそうです。そこが一番ネックかも知れません。
TasogareKK

2017/03/17 13:13

コメント ありがとうございます。 まず Java9も試してみましたが TableViewどころか Scene で つまづきました。正式版まで待ちます。 ReferenceError: "Scene" is not defined 今後の進め方ですが いけるとこまで javascriptで やってみます。不安ではありますが。。。 たくさんの事を お教えいただき ありがとうございました。 何故か Chromium/win7 で コメントボタンが効かなくなり 返信が遅れました。失礼いたしました。 このコメントは FireFox/ubuntu で 書きました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問