JavaFX - 移动 ListView 项目 - MVC

JavaFX - move ListView Item - MVC

我是这个 java/javafx 的新手,如果有人能帮助我解决这个问题,我将非常高兴。

我有以下代码:

// Main.java

package lernen;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application
{
    @Override
    public void start(Stage primaryStage)
    {
        Presenter p = new Presenter();
        View v = new View(p);
        Model m = new Model();

        p.setModel(m);
        p.setView(v);

        Scene scene = new Scene(v.getUI());
        primaryStage.setTitle("Schiebefenster");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

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

// View.java

package lernen;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.layout.GridPane;

public class View
{
    private Presenter presenter;

    private GridPane pane;

    private Button b1, b2;

    private Label l1, l2;

    // private ObservableList<String> candidates = FXCollections.observableArrayList("a", "b", "c", "d");
    private ObservableList<String> candidates = FXCollections.observableArrayList();

    private ListView<String> list = new ListView<>(candidates);

    private ObservableList<String> selected = FXCollections.observableArrayList();

    private ListView<String> list2 = new ListView<>(selected);

    public View(Presenter presenter)
    {
        this.presenter = presenter;
        initView();
    }

    private void initView()
    {
        pane = new GridPane();
        pane.setVisible(true);
        l1 = new Label("Buchstabe");
        pane.add(l1, 0, 0);
        l2 = new Label("Selektiert");
        pane.add(l2, 4, 0);
        b1 = new Button("<");
        pane.add(b1, 2, 2);
        b2 = new Button(">");
        pane.add(b2, 2, 3);
        // list = new ListView<String>();
        pane.add(list, 0, 1, 2, 5);
        // list2 = new ListView<>();
        pane.add(list2, 4, 1, 2, 5);


        b2.setOnAction((ActionEvent) -> {
            String potential = list.getSelectionModel().getSelectedItem();
            if (potential != null)
            {
                list.getSelectionModel().clearSelection();
                candidates.remove(potential);
                selected.add(potential);
            }
        });

        b1.setOnAction((ActionEvent) -> {
            String selectedItem = list2.getSelectionModel().getSelectedItem();
            if (selectedItem != null)
            {
                list2.getSelectionModel().clearSelection();
                selected.remove(selectedItem);
                candidates.add(selectedItem);
            }
        });

    }

    public GridPane getUI()
    {
        return pane;
    }

    public ListView<String> getList()
    {
        return list;
    }

    public ListView<String> getList2()
    {
        return list2;
    }

}

// Presenter.java

package lernen;

public class Presenter
{
    private View view;

    private Model model;

    public Presenter()
    {
    }

    public void setView(View view)
    {
        this.view = view;
        this.view.getList().setItems(model.getData());
    }

    public void setModel(Model model)
    {
        this.model = model;
    }

}

// Model.java

package lernen;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

public class Model
{
    private ObservableList<String> data = FXCollections.observableArrayList();

    public Model()
    {
        data.addAll("a", "b", "c", "d", "e");
    }

    public ObservableList<String> getData()
    {
        return data;
    }

}

给定的任务是根据 MVP 模式将项目从左侧列表移动到右侧,反之亦然。问题是:如果我将一个字母移到右侧,左侧的字母仍然存在。我希望你们能帮我解决这个问题。 提前致谢!

在您调用的演示器中

this.view.getList().setItems(model.getData());

所以列表将显示模型 ObservableList 中定义的项目,因此,当在 b2 的事件处理程序中调用

candidates.remove(potential);

您实际上尝试从另一个列表(实际上是空的)中删除该项目。

我想混淆来自以下方面:

您定义了一个 ObservableList,并指定此列表作为您 ListView 的数据模型。

private ObservableList<String> candidates = FXCollections.observableArrayList();
private ListView<String> list = new ListView<>(candidates);

然后当您在控制器中调用时

this.view.getList().setItems(model.getData());

你认为,这将用存储在模型中的 ObservableList 的元素填充 candidates ObservableList(模型中列表中的所有元素都将被复制到此列表)。但是,当您调用 setItems 时,您将存储在 itemsProperty 中的引用设置为指定 ObservableList,因此它将指向存储在模型中的 ObservableList 而不再至 candidates.

您可以将此行修改为:

this.view.getList().getItems().addAll(model.getData());

不同的是,在这种情况下,getItems() 将 return 中的 ObservableList 存储在 itemsProperty 中,然后将所有元素从模型中复制到这个列表,但它仍将指向 candidates。在这种情况下,模型中的 ObservableList 未被触及。

或者您可以将您的听众更改为:

view.getList2().getItems().remove(selectedItem);

这也会从模型中的 ObservableList 中删除元素。

情况和这里基本一样:

// presenter.java

package lernen;

public class Presenter
{
    private View view;

    private Model model;

    public Presenter()
    {
    }

    public void setView(View view)
    {
        this.view = view;
        this.view.getList().setItems(model.getData());
    }

    public void setModel(Model model)
    {
        this.model = model;
    }

    public void RightToLeft() {
        System.out.println("RightToLeft triggered.");
        String selectedItem = view.getList2().getSelectionModel().getSelectedItem();
        if (selectedItem != null)
        {
            view.getList2().getSelectionModel().clearSelection();
            view.getList2().getItems().remove(selectedItem);
            view.getList().getItems().add(selectedItem);
        }
    }

    public void LeftToRight() {
        System.out.println("LeftToRight triggered.");
        String selectedItem = view.getList().getSelectionModel().getSelectedItem();
        if (selectedItem != null)
        {
            view.getList().getSelectionModel().clearSelection();
            view.getList().getItems().remove(selectedItem);
            view.getList2().getItems().add(selectedItem);
        }
    }

}

// view.java

package lernen;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.layout.GridPane;

public class View
{
    private Presenter presenter;

    private GridPane pane;

    private Button b1, b2;

    private Label l1, l2;

    private ObservableList<String> candidates = FXCollections.observableArrayList();

    private ListView<String> list = new ListView<>(candidates);

    private ObservableList<String> selected = FXCollections.observableArrayList();

    private ListView<String> list2 = new ListView<>(selected);

    public View(Presenter presenter)
    {
        this.presenter = presenter;
        initView();
    }

    private void initView()
    {
        pane = new GridPane();
        pane.setVisible(true);
        l1 = new Label("Buchstabe");
        pane.add(l1, 0, 0);
        l2 = new Label("Selektiert");
        pane.add(l2, 4, 0);
        b1 = new Button("<");
        pane.add(b1, 2, 2);
        b2 = new Button(">");
        pane.add(b2, 2, 3);
        list = new ListView<String>();
        pane.add(list, 0, 1, 2, 5);
        list2 = new ListView<>();
        pane.add(list2, 4, 1, 2, 5);

        b1.setOnAction(e -> presenter.RightToLeft());
        b2.setOnAction(e -> presenter.LeftToRight());
    }

    public GridPane getUI()
    {
        return pane;
    }

    public ListView<String> getList()
    {
        return list;
    }

    public ListView<String> getList2()
    {
        return list2;
    }

}