4

私はこのJavaFX2ガイドに従おうとしています。

http://docs.oracle.com/javafx/2/ui_controls/table-view.htm#CJAGAAEE

私はJavaの代わりにScalaを使用していますが、私にとっては次のようになります。

<TableView fx:id="test">
     <columns>
         <TableColumn prefWidth="75.0" text="Message" />
     </columns>
</TableView>

そしてコード:

val c = test.getColumns.get(0) // Get the first column.
c.setCellValueFactory(new PropertyValueFactory[Foo, _]("message")) // Foo is my model with a single SimpleStringProperty called "message".

val observableFoos = FXCollections.observableList(foos)
test.setItems(observableFoos)

私が抱えている問題は、そのsetCellValueFactory行が次の原因になることです。

エラー:クラスタイプが必要ですが、javafx.scene.control.cell.PropertyValueFactory [com.myapp.models.Foo、_]がc.setCellValueFactory(new PropertyValueFactoryFoo、_)を検出しました

この方法をどのように使用するのかわかりません。に置き換える_String、次のようになります。

エラー:タイプの不一致。見つかった:javafx.scene.control.cell.PropertyValueFactory [com.myapp.models.Foo、String]必須:javafx.util.Callback [javafx.scene.control.TableColumn.CellDataFeatures [com.myapp.models.Foo、?0 ]、javafx.beans.value.ObservableValue [?0]]ここで、タイプ?0 c.setCellValueFactory(new PropertyValueFactoryFoo、String)

行を削除すると、すべてが正常に機能することを確認できますsetCellValueFactory。テーブルにコンテンツが表示されないだけです。期待どおりに行が空白になっているだけです。

4

2 に答える 2

5

TL; DR: Javaでは、型パラメーターに関して型の安全性を黙ってバイパスするのは簡単です。Scalaは、明示的なキャストを実行することを除いて、それを許可しません。さらにTable.getColumns、列を取得するために使用すると、セルのタイプが失われます。解決策:インスタンスを適切なタイプにキャストするTableColumnか、手動で列をインスタンス化します。

最初の問題は、の署名にありTable.getColumnsます:それはを返します( http://docs.oracle.com/javafx/2/api/javafx/scene/control/TableView.html#getColumnsObservableList[TableColumn[S,_]] ()を参照)。したがって、valは。と入力されます。これは、セルコンテンツのタイプ(2番目のタイプパラメーターで示される)が失われることを意味します。cTableColumn[Foo,_]

ここでの唯一の解決策はc、キャストを使用して列()を適切に入力することです。

val c = test.getColumns.get(0).asInstanceOf[TableColumn[Foo, String]]
c.setCellValueFactory(new PropertyValueFactory[Foo, String]("message"))

これは非常に論理的です。各列に異なるタイプのオブジェクトを含めることができる列のリストがあります。異なるタイプのオブジェクトを含むscalaリストで同じジレンマに直面しますが、すべて先験的には不明です。キャスト(または変装したキャストであるタイプの一致)のみが、コンパイル時に特定のタイプを取り戻すことができます時間。

また、Web上の多くのJavaFxの例では、。を介して列を取得しないことにも注意してくださいTable.getColumns。代わりに、それらを手動でインスタンス化し、setCellValueFactory直後に呼び出します。同じことを行うと、タイプパラメータを自分で指定するため、(キャストを必要とせずに)問題を解決できます。

val c = new TableColumn[Foo, String] // See ma, no cast!
c.setCellValueFactory(new PropertyValueFactory[Foo, String]("message"))

ここで、いくつかのJavaの例を見て、それらをインスタンス化するときに実際には型パラメーターを提供しないTableColumnことに気付くかもしれません。

TableColumn c  = new TableColumn();    
c.setCellValueFactory( new PropertyValueFactory<Foo,String>("name"));

そして確かにそれはコンパイルします。どうして?悲しい真実は、上記のコードは、ジェネリックス以前のクラスに対するJavaの下位互換性に依存しているため、キャストを実行するよりも安全ではないということです。つまり、は例では なくc正義として入力されるため、Javaコンパイラはそれを非ジェネリッククラスとして扱い、の型パラメータに関する型チェックを実行しません。これを、タイプをジェネリックタイプに明示的に設定した場合に何が起こるかと比較してください(ただし、セルタイプは不明です)。TableColumnTableColumn<?, String>TableColumnc

TableColumn<Foo, ?> name  = new TableColumn("Name");
name.setCellValueFactory( new PropertyValueFactory<Room,String>("name"));

この場合、コンパイラは型の不一致エラーを発行します。

error: method setCellValueFactory in class TableColumn<S,T> cannot be applied to given types;
...

cこれは、TableColumn [Foo、_]と入力したときのscalaの場合と同じです。

于 2012-10-10T14:50:27.900 に答える
1

長い形式を使用することをお勧めしますPropertyValueFactory:(
申し訳ありませんが、私はScalaに精通していないため、Javaで記述しています)

 c.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<Foo, String>,
             ObservableValue<String>>() {
     public ObservableValue<String> call(TableColumn.CellDataFeatures<Foo, String> f) {
         // f.getValue() returns the Foo instance for a particular TableView row
         return f.getValue().messageProperty();
         // or
         return new SimpleStringProperty(p.getValue().getMessage());
         // if you omit messageProperty() in Foo model class.
         // However omitting it, causes the property listener could not be attached resulting 
         // unable to refresh (synchronize) tableview row item value when the backing 
         // Foo's message value is changed.
     }
  });

Fooモデルは次のようなものでなければならないことに注意してください。

public class Foo {
    private SimpleStringProperty message;

    public SimpleStringProperty messageProperty() {
        return message;
    }

    public String getMessage() {
        return message.get();
    }

    public void setMessage(String message) {
        this.message.set(message);
    }
}
于 2012-10-10T08:09:09.817 に答える