2017-10-23 1 views
-1

가 I가 ObservableList하여있는 TableView를 백업 한 :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; 
    // ... 
} 

을 코드의이 작품에서 나는 얻을의 TableView에서 선택한 모든 항목 처리 :

private void approveSelectedRenderers() { 
    ObservableList<Renderer> selectedRenderers = renderersTable.getSelectionModel().getSelectedItems(); 

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

다중 선택을 사용하도록 설정했으며 실제로 선택한 순환자가 적절한 개수를 표시하지만 루프는 한 번 실행. 대신 경우

나는 다음과 같이 복사본을 만들 : 그것은 올바른 작동하고 모든 항목이 처리되는

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의 백업 (관찰 가능) 데이터 구조를 수정하고 있습니다. 즉, 선택한 전체 (관찰 가능) 목록을 백업 데이터 구조의 렌더러로 다시 설정하는 것입니다. Im 그것은 얼마간 ConcurrentModificationException 던지기를 다소 놀라게했다.

해결 방법 : 선택한 목록을 반복 할 때 백업 데이터 구조를 수정하지 마십시오. 업데이트 후에도 재설정 할 필요가 없습니다. 값 유형 (부울)을 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 (...)'호출을 필요로하지 않을 것입니다. –

관련 문제