JavaFX случайным образом заполняет ListViews - PullRequest
1 голос
/ 22 января 2020

Я пытался создать программу, в которую вы можете добавлять имена в виде флажков. Проверяя их и нажимая кнопку рандомизации, все имена будут помещены в 2 разных ListViews (каждое имя может быть размещено только один раз, и каждый ListView должен иметь одинаковое количество имен или еще 1 имя внутри). Я понятия не имею, как это должно быть написано в разделе «onRandom».

package sample;


import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.scene.layout.VBox;
import java.util.Objects;


public class Controller {

    @FXML
    private Button add;
    @FXML
    private Button delete;
    @FXML
    private VBox vbox;
    @FXML
    private TextField text;
    @FXML
    private Button random;
    @FXML
    private ListView listview1;
    @FXML
    private ListView listview2;
    @FXML
    private CheckBox cb;




    @FXML
    void initialize() {

    }

    @FXML
    public void onEnter(ActionEvent e){
        CheckBox cb = new CheckBox(text.getText());
        vbox.getChildren().add(cb);
        if (text.getText().matches("")) {
            vbox.getChildren().remove(cb);
        }
    }

    @FXML
    public void onAdd(ActionEvent e) {
        CheckBox cb = new CheckBox(text.getText());
        vbox.getChildren().add(cb);
        if (text.getText().matches("")) {
            vbox.getChildren().remove(cb);
        }
    }
    @FXML
    public void onDelete(ActionEvent e) {
        vbox.getChildren().removeIf(child -> ((CheckBox) child).isSelected());
    }

    @FXML
    public void onRandom(ActionEvent e) {
        vbox.getChildren()
                .stream()
                .map(item -> (CheckBox) item)
                .filter(item -> item.isSelected())
                .filter(value -> Objects.nonNull(value))
                .forEach(value -> {
                    listview1.getItems().add(value.getText());
                    listview2.getItems().add(value.getText());
                });
        }
}

Этот ниже только для тестирования.

.forEach(value -> {
                    listview1.getItems().add(value.getText());
                    listview2.getItems().add(value.getText());
                });

Вот мой файл F XML https://pastebin.com/9v8e0c0Y

1 Ответ

2 голосов
/ 22 января 2020

Используйте Collections.shuffle для создания случайной перестановки списка, затем добавьте первую половину к одному ListView, а остальные к другому.

// do not use raw types
@FXML
private ListView<String> listview1;
@FXML
private ListView<String> listview2;
...

private final Random randomNumberGenerator = new Random();
List<String> items = new ArrayList<>(); // copy children to new list

// the following loop imho is easier to comprehend than the Stream implementation
for (Node child : vbox.getChildren()) {
    CheckBox cb = (CheckBox) child;
    if (cb.isSelected) {
        items.add(cb.getText());
    }
}

Collections.shuffle(items, randomNumberGenerator);
final int size = items.size();
final int half = size / 2;

// add first half to first ListView and second half to second ListView
listview1.getItems().setAll(items.sublist(0, half));
listview2.getItems().setAll(items.sublist(half, size));

Обратите внимание, что некоторые вызовы методов на Stream на самом деле не нужны в вашем случае:

.filter(value -> Objects.nonNull(value))

Проверка для null никогда не требуется для списка children Parent , Реализация списка запрещает вставку null в этот список. Предыдущий фильтр выбрасывал NPE в тех случаях, когда этот предикат в любом случае дает false. В тех случаях, когда вам нужен такой предикат, вы можете использовать ссылку на метод для сокращения кода:

.filter(Objects::nonNull)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...