2017-10-23 11 views
-1

私はObservableListに裏打ちされたテーブルビューがあります。なぜJavaFX TableViewから選択した項目のリストをコピーする必要がありますか?

private ObservableList<Renderer> renderers = FXCollections.observableArrayList(); 

@FXML 
private TableView<Renderer> renderersTable; 
@FXML 
private TableColumn<Renderer, String> nameColumn; 
@FXML 
private TableColumn<Renderer, Boolean> approvedColumn; 

@FXML 
private void initialize() { 
    nameColumn.setCellValueFactory(new PropertyValueFactory<>("name")); 
    approvedColumn.setCellValueFactory(new PropertyValueFactory<>("approved")); 
    renderersTable.setItems(this.renderers); 
} 

レンダラオブジェクトは非常に単純であり、次のようになります。このコードの一部で

@Data 
@NoArgsConstructor 
@EqualsAndHashCode(callSuper = false) 
public class Renderer extends Model { 
    private String name; 
    private boolean approved; 
    // ... 
} 

を私がテーブルビューから選択されたすべてのアイテムを取得します

複数の選択を有効にして、実際には選択したレンダラーが適切なカウントを表示していますが、ループは一度実行する。

private void approveSelectedRenderers() {   
    // Get all the selected renderers but copy them. 
    List<Renderer> selectedRenderers = new ArrayList<>();   
    selectedRenderers.addAll(renderersTable.getSelectionModel().getSelectedItems()); 

    for (Renderer renderer : selectedRenderers) { 
     renderer.setApproved(true); 
     renderers.set(renderers.indexOf(renderer), renderer); 
    } 
} 

それが正しい動作し、すべての項目が処理されます。

代わりにした場合、私はこのように、コピーを作成します。どうしたの?これに対処する適切な方法は何ですか?

+0

データ構造のための 'allRenderes'とは何ですか?それは別のデータ構造か、 'TableView'の(観測可能な)バッキングデータ構造ですか? – n247s

+1

あなたの他の質問と同じように、あなたはそのようなことを何もする必要はありません。投稿していないコードのどこかにエラーがあると、あなたはこれらの不要なフープを飛び越えなければならないと信じさせています。 –

+0

@ n247s:それは、TableViewを支持する観測可能です。 – Pablo

答えて

0

他の質問から判断すると、実際にはTableViewのバッキング(観測可能な)データ構造が変更されています。つまり、選択した(観測可能な)リスト全体をリセットして、バッキングデータ構造のレンダラーをリセットします。私はちょっと驚いたそれはConcurrentModificationExceptionをスローしません。

解決策:選択したリストをループするときにバッキングデータ構造を変更しないでください。更新後にリセットする必要もありません。値の型(boolean)をSimpleBooleanPropertyに変更すると、CellFactoryを使用して直接TableViewに渡すことができます。 SimpleBooleanPropertyの値を変更すると、自動的にテーブルが更新されます。

SimpleBooleanPropertyを使用することができない場合は、TableView#refresh()メソッドを使用することもできます。ただし、変更された要素だけではなく、TableView全体が再投入されることに注意してください。

さらに読む:Simular SO question

+0

"変更された要素だけでなく、TableView全体が再作成されることに注意してください。" AFAIKは可視セルを再描画するだけです。あなたのユーザーが巨大な画面を持っていない限り、20行以上の行を表示することはほとんどありません。 –

+0

しかし、選択した行をループして変更する必要があります。それをしないことは何もしないか、私がすでにやっていることをコピーしていることです。 – Pablo

+1

@Pabloリストを反復して内容を変更するためにリストをコピーする必要はありません。リストをコピーせずに(この答えで説明したように)リストをコピーしてもコードが動作しない唯一の理由は、反復処理中に 'renderers.set(...)'を呼び出すことです。反復する。この呼び出しを削除すると、ループは期待通りに実行されます。'TableColumn'と' PropertyValueFactory'のJavadocで提案されているようにあなたのモデルを実装するなら、 'renderers.set(...)'コールは必要ないでしょう。 –

関連する問題