2016-11-21 3 views
1

Извините, что беспокоился об этой широко обсуждаемой теме. Я создаю диалог для выбора строковых значений из одного списка в другой. В начале есть список опций. получить/setSourceItems и получить/setTargetItems являются методы получения и установки для ObservableListsКак обновить ListView в JavaFX

private ListView<String> sourceListView; 
private ObservableList<String> sourceItems; 
private ListView<String> targetListView; 
private ObservableList<String> targetItems; 

     List<String> options = getSelectedMetaDataList(); 
     setSourceItems(FXCollections.observableArrayList(options)); 
     sourceListView = new ListView(getSourceItems()); 
     setTargetItems(FXCollections.observableArrayList(new ArrayList())); 
     targetListView = new ListView(getTargetItems()); 

Диалог показывает ListViews хорошо в начале. Источник заполняется опциями, а цель пуста. Но когда я использую кнопку, в пользовательском интерфейсе ничего не происходит. Например, когда я перемещаю все элементы из источника в цель, я вижу элементы в targetItems observableList, но ничего в targetListView в пользовательском интерфейсе.

 Button selectAllBtn = new Button(">>"); 
      selectAllBtn.setOnAction(new EventHandler<ActionEvent>() { 
       @Override 
       public void handle(ActionEvent event) { 
        if (getSourceItems().size() > 0) { 
         setTargetItems(getSourceItems()); 
         targetListView.refresh(); 
         setSourceItems(null); 
         sourceListView.refresh(); 
         System.out.println("selectAllBtn target: " + getTargetItems().toString()); 
        } 
       } 
      }); 

Что-то не так с моделью выбора тоже. Потому что, когда я пытаюсь переместить выбранные элементы sourceListView.getSelectionModel(), getSelectedItems() пуст, даже когда я выделил элемент. Я пытался перемещать объекты не только с помощью наблюдаемого списка, но и с помощью targetListView.getItems(). AddAll (movingItems); По-прежнему никаких изменений в пользовательском интерфейсе.

 Button selectOneBtn = new Button(">"); 
      selectOneBtn.setOnAction(new EventHandler<ActionEvent>() { 
       @Override 
       public void handle(ActionEvent event) { 
        ObservableList<String> movingItems = sourceListView.getSelectionModel().getSelectedItems(); 
        System.out.println("selectOneBtn: " + sourceListView.getSelectionModel().getSelectedItems().size()); 
        System.out.println("selectOneBtn: " + targetListView.getSelectionModel().getSelectedItems().size()); 
        if (movingItems.size() > 0) { 
        System.out.println("selectOneBtn: " + movingItems.toString()); 
        sourceListView.getSelectionModel().clearSelection(); 
        sourceListView.getItems().removeAll(movingItems); 
        sourceListView.refresh(); 
        targetListView.getItems().addAll(movingItems); 
        targetListView.refresh(); 
        System.out.println("selectOneBtn source: " + getSourceItems().toString()); 
        System.out.println("selectOneBtn target: " + getTargetItems().toString()); 
        } 
       } 
      }); 

Заранее спасибо.

+3

Вы, мой друг, усложнили простую задачу. – Sedrick

+1

Я предлагаю вам избавиться от ваших сеттеров и геттеров и использовать ListView и ObservableList, как они были предназначены. – Sedrick

+1

Или, по крайней мере, избавиться от сеттеров. 'ObservableList' обычно лучше всего работают, если они являются окончательными. Поскольку они изменяемы, редко приходится менять ссылки, чтобы указать на новый список. –

ответ

0

Вы можете изменить основной наблюдаемый список, но вы никогда не говорите вид списка, чтобы использовать новый список:

Button selectAllBtn = new Button(">>"); 

selectAllBtn.setOnAction(new EventHandler<ActionEvent>() { 
    @Override 
    public void handle(ActionEvent event) { 
     if (getSourceItems().size() > 0) { 
      setTargetItems(getSourceItems()); 

      targetListView.setItems(getTargetItems()); 

      // use an empty list, not null: 
      setSourceItems(FXCollections.observableArrayList()); 

      sourceListView.setItems(getSourceItems()); 

      System.out.println("selectAllBtn target: " + getTargetItems().toString()); 
     } 
    } 
}); 

В качестве альтернативы, вместо изменения в новый список, просто изменить содержимое существующего списка. Поскольку списки являются наблюдаемыми, то ListViews будет видеть изменения автоматически:

Button selectAllBtn = new Button(">>"); 

selectAllBtn.setOnAction(new EventHandler<ActionEvent>() { 
    @Override 
    public void handle(ActionEvent event) { 
     if (getSourceItems().size() > 0) { 

      getTargetItems().setAll(getSourceItems()); 

      getSourceItems().clear(); 

      System.out.println("selectAllBtn target: " + getTargetItems().toString()); 
     } 
    } 
}); 

Для вашей проблемы выбора, вы получите ссылку на список выбранных элементов:

ObservableList<String> movingItems = sourceListView.getSelectionModel().getSelectedItems(); 

а затем очистить выбор :

sourceListView.getSelectionModel().clearSelection(); 

который, конечно же, сделает список выбранных элементов пустым.

Так что теперь, когда вы делаете

sourceListView.getItems().removeAll(movingItems); 
targetListView.getItems().addAll(movingItems); 

вы передаете в пустом списке каждый раз, и поэтому ничего не изменится.

Вместо копировать выбранные элементы:

List<String> movingItems = new ArrayList<>(sourceListView.getSelectionModel().getSelectedItems()); 

, а затем

sourceListView.getItems().removeAll(movingItems); 
targetListView.getItems().addAll(movingItems); 

будет иметь желаемый эффект (нет необходимости вызывать refresh()).

Вот SSCCE (обратите внимание, я объединил оба поведения в одном методе, так как они по существу то же самое):

import java.util.ArrayList; 
import java.util.List; 

import javafx.application.Application; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.geometry.Pos; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.ListView; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.VBox; 
import javafx.stage.Stage; 

public class MoveItemsBetweenListViews extends Application { 

    private ObservableList<String> sourceItems; 
    private ObservableList<String> targetItems; 



    @Override 
    public void start(Stage primaryStage) { 
     sourceItems = FXCollections.observableArrayList("One", "Two", "Three", "Four"); 
     targetItems = FXCollections.observableArrayList(); 

     ListView<String> sourceListView = new ListView<>(sourceItems); 
     ListView<String> targetListView = new ListView<>(targetItems); 

     Button moveAllButton = new Button(">>"); 
     Button moveSelectedButton = new Button(">"); 

     moveAllButton.setOnAction(e -> moveItems(sourceItems)); 
     moveSelectedButton.setOnAction(e -> moveItems(sourceListView.getSelectionModel().getSelectedItems())); 

     VBox buttons = new VBox(10, moveAllButton, moveSelectedButton); 
     buttons.setAlignment(Pos.CENTER); 

     BorderPane root = new BorderPane(buttons, null, targetListView, null, sourceListView); 
     Scene scene = new Scene(root, 600, 600); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    private void moveItems(List<String> itemsToMove) { 
     List<String> movingItems = new ArrayList<>(itemsToMove); 
     sourceItems.removeAll(movingItems); 
     targetItems.addAll(movingItems); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 
+0

Привет. Спасибо за ваш ответ. Я попробовал оба предложения об обновлении, но ничего не изменилось. Теперь я обнаружил, что sourceItems и targetItems определяются как ObservableList . Я где-то читал, что правильный тип si ObservableListArray. –

+0

@EduardNickel Нет, 'ObservableList ' правильный. Если он все еще не работает, что-то еще не так в коде, который вы еще не опубликовали. См. Обновление, которое включает рабочий SSCCE. –

+0

Спасибо. SSCCE отлично работает и отлично работает. Что может повлиять на такое простое поведение? Как я уже писал, моя кнопка находится в диалоговом окне. Возможно, это влияет на весь процесс :( –

0

Я мог бы смотреть на вас проблемы неправильно, но мне кажется, что вы упростила сложную задачу. ListView и ObservableList были простыми и упрощали обновление/обновление ListView.Я думаю, вы должны заставить ваш метод getSelectedMetaDataList() возвращать ArrayList, тогда вы должны создать ObservableList, загрузив его с помощью ArrayList. Затем вы должны использовать ObservableList и ListView соответственно. Оттуда вы должны использовать методы ObservableList для выполнения того, что вы пытаетесь сделать.

 ArrayList<String> options = getSelectedMetaDataList();//Make this method return an ArrayList 
     ObservableList<String> items = FXCollections.observableArrayList(options); 
     ListView targetListView = new ListView(); 
     targetListView.setItems(items); 
+0

Спасибо. Я стараюсь, как новичок может попробовать :) Для меня ObservableList items = FXCollections.observableArrayList (Список ); такой же, как ObservableList items = FXCollections.observableArrayList (ArrayList ); Outocome ObservableList ;) –

+0

setSourceItems (FXCollections.observableArrayList (опции)); Я думаю, что это плохая идея. В основном это FXCollections.observableArrayList (параметры). Нет определенного наблюдаемого арриалиста. Это мое предположение, почему у вас есть проблема. – Sedrick

+0

sourceItems и targetItems ObservableList Я удаляю геттеры и сеттеры. У меня есть метод change getSelectedMetaDataList() и теперь возвращает ArrayList , но у меня все еще нет успеха. :( –

0

Я предполагаю, что вы пытаетесь сделать что-то похожее на это.

@FXML ListView lv1, lv2; 

ArrayList options = new ArrayList(); 
ObservableList<String> items; 

ObservableList<String> items2; 


//This is used to get the selected item from lv1 and add it to lv2 
@FXML 
private void handleButtonAction(ActionEvent event) { 
    items2.add(lv1.getSelectionModel().getSelectedItem().toString());    
} 

//This is used to get all items from lv1 and add them to lv2 
@FXML 
private void handleGetAllButtonAction(ActionEvent event) 
{ 
    for(String entry : items) 
    { 
     items2.add(entry); 
    } 
} 

@Override 
public void initialize(URL url, ResourceBundle rb) { 
    // TODO 

    options.add("hello"); 
    options.add("bye"); 
    options.add("hola"); 
    items = FXCollections.observableArrayList(options); 
    items2 = FXCollections.observableArrayList(); 

    System.out.println(items.size()); 
    lv1.setItems(items); 
    lv2.setItems(items2); 

}  
+0

@Eduard Как это было? – Sedrick