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

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

ただいまの
回答率

90.33%

  • JavaScript

    17550questions

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

  • JavaFX

    410questions

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

nashorn + JavaFX + TableView で エラー発生

解決済

回答 1

投稿 編集

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

TasogareKK

score 4

先日コチラでお教えいただき 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

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.VBox?>
<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">
   <children>
      <TableView id="TB0000" fx:id="TB0000" prefHeight="200.0" prefWidth="200.0" />
   </children>
</VBox>
//==============================================================================
var File              = Java.type('java.io.File');
var FXMLLoader        = Java.type('javafx.fxml.FXMLLoader');
var ComboBoxTableCell = Java.type('javafx.scene.control.cell.ComboBoxTableCell');
load('fx:base.js');
load('fx:fxml.js');
load('fx:controls.js');
var TB0000,Col000;
//==============================================================================
function file2URL(file){return new File(file).toURI().toURL();}
//==============================================================================
function start(stage){
    //--------------------------------------------
    var fxml = './1000.fxml';
    var root = FXMLLoader.load(file2URL(fxml));
    //--------------------------------------------
    TB0000 = root.lookup('#TB0000');
    //--------------------------------------------
    var Cds000 = [
        {'id':"CODE",'tx':"コード",'wd': 90,'ag':"CC",'inp':"V",'fw':"N",'bC':"240,240,240",'fC':" 30, 40, 50",'tp':'S','defV':'Z_9999'},
        {'id':"NAME",'tx':"名前",  'wd':120,'ag':"CL",'inp':"T",'fw':"N",'bC':"240,255,255",'fC':" 30, 40,120",'tp':'S','defV':'X'},
        {'id':"BRTH",'tx':"誕生日",'wd':108,'ag':"CC",'inp':"V",'fw':"N",'bC':"255,255,255",'fC':"180, 80,100",'tp':'D','defV':'X'},
        {'id':"AGES",'tx':"年齢",  'wd': 60,'ag':"CR",'inp':"V",'fw':"B",'bC':"255,255,255",'fC':"  0,100,180",'tp':'I','defV':'0'}
    ]; // Column.Design
    //--------------------------------------------
    var Dat000 = [
        ['A_1234','Tasogare','1980/01/01','36'],
        ['B_5678','ほげ太郎','2010/01/01']       // 最終フィールド欠落
    ]; // ソースは CSV.load や SQL.結果set の 予定故 文字列の2次元配列を 準備
    //--------------------------------------------
    Col000 = setTBL(TB0000,Cds000,Dat000);
    //--------------------------------------------
    stage.title = 'TEST';
    stage.setScene(new Scene(root));
    stage.show();
    //--------------------------------------------
    // toDo = 入力IF(Text,Combo),入力完了イベント,行内自動演算,err.Check,,,,,,集計行,新規行,行並替
}
//==============================================================================
//ココから下は libTBL.js として 独立させる予定
//==============================================================================
var FXCollections = Java.type('javafx.collections.FXCollections')
var aryAlg       = [];
        aryAlg['CC'] = 'CENTER;';
        aryAlg['CL'] = 'CENTER-LEFT;';
        aryAlg['CR'] = 'CENTER-RIGHT;';
var aryFnW       = [];
        aryFnW['N']  = 'normal;';
        aryFnW['B']  = 'bold;';
//   型(tp) = [ S(string) D(date/time) I(int) R(real) ]
// 入力(in) = [ V(view) T(TextField) C(ComboBox) ]
//==============================================================================
function setTBL(TBL,aryCds,aryDat){
    //--------------------------------------------
    TBL.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
    TBL.getSelectionModel().setCellSelectionEnabled(true);
    TBL.setStyle("-fx-font-family:'Courier New',monospace;");
    TBL.setStyle("-fx-font-size:14;");
    TBL.setEditable(true);
    //--------------------------------------------
    // column
    var aryCol = [];
    for(var cc=0;cc<aryCds.length;cc++){
        //------------------
        var _Cds = aryCds[cc];
        //------------------
        var styC  = '';
                styC += '-fx-padding:2px 4px;';                       // padding
                styC += '-fx-alignment:'   + aryAlg[_Cds.ag];         // alignment
                styC += '-fx-font-weight:' + aryFnW[_Cds.fw] ;        // フォント.weight
                styC += '-fx-text-fill:       rgb(' + _Cds.fC + ');'; // 前景色
        //------------------
        var tCol = new TableColumn(_Cds.tx); // text
                tCol.id        = _Cds.id;        // id (不要?)
                tCol.prefWidth = _Cds.wd;        // 幅
                tCol.setStyle(styC);             // スタイル
                valFac(tCol,_Cds.inp,_Cds.tx);   // cellValueFactory
        //------------------
        TBL.getColumns().add(tCol);
        aryCol.push(tCol);
        //------------------
    }
    //--------------------------------------------
    // data
    var objDat = [];
    for(var c0=0;c0<aryDat.length;c0++){
        var ob = {};
        for(var c1=0;c1<aryCds.length;c1++){
            if(aryDat[c0].length>c1){
                ob[aryCds[c1].tx] = aryDat[c0][c1];
            }else{
                ob[aryCds[c1].tx] = aryCds[c1].defV;
            }
        }
        objDat.push(ob);
    }
    TBL.setItems(FXCollections.observableList(objDat));
    //--------------------------------------------
    return aryCol;
    //--------------------------------------------
}
//==============================================================================
function valFac(tCol,inp,tx){
    if(inp=='V'){
        tCol.cellValueFactory = function(p){
            var x = p.getValue()[tx];
            return new ReadOnlyObjectWrapper(x);
        }
    }
    if(inp=='T'){
        //tCol.cellValueFactory = ( /* TextField */ );
    }
}
//==============================================================================
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • KSwordOfHaste

    2017/03/10 08:44

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

    キャンセル

回答 1

checkベストアンサー

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 23: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ですが
    特にこだわりもありませんので 楽な方を選びたいと思います。

    たくさんアドバイスいただきましたが
    しばらく考えてから結論を出す事にします。

    キャンセル

  • 2017/03/10 23:23

    SINGLEに変えてもダメでしたか・・・ということは自分の予想は外れかも知れません。
    (自分には質問者さんのコードに問題があるように見えないのです。)

    なお、目指すアプリの程度であればあえてJavaでデータクラスを作る必要性もないような気がしました。つまりJavascriptで作っても充分な気がします。ただJava側で問題が起こったときJavaのデバッグができないと問題の解決に時間がかかりそうです。そこが一番ネックかも知れません。

    キャンセル

  • 2017/03/17 22:13

    コメント ありがとうございます。

    まず Java9も試してみましたが TableViewどころか
    Scene で つまづきました。正式版まで待ちます。
    ReferenceError: "Scene" is not defined

    今後の進め方ですが いけるとこまで javascriptで
    やってみます。不安ではありますが。。。

    たくさんの事を お教えいただき ありがとうございました。

    何故か Chromium/win7 で コメントボタンが効かなくなり
    返信が遅れました。失礼いたしました。
    このコメントは FireFox/ubuntu で 書きました。

    キャンセル

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

  • JavaScript

    17550questions

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

  • JavaFX

    410questions

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