【问题标题】:Javafx Link/Bind Treeview Items to ObservableListJavafx 将 Treeview 项链接/绑定到 ObservableList
【发布时间】:2019-01-18 03:08:28
【问题描述】:

我正在尝试找到一种简单的方法将下载类型的 TreeView 链接到相同类型的 ObservableList

MainController.java

public class MainController {

    private ObservableList<Download> downloads = FXCollections.observableArrayList();
    @FXML private TreeView<Download> $TreeDownloads;

    @FXML
    public void initialize() {
        $TreeDownloads.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
        $TreeDownloads.setNodeOrientation(NodeOrientation.LEFT_TO_RIGHT);
        $TreeDownloads.setShowRoot(false);

        downloads.addListener(new ListChangeListener<Download>() {
            @Override
            public void onChanged(Change<? extends Download> c) {
                if (c.wasAdded()) {
                    addDownloads(c.getAddedSubList());
                }
                if (c.wasRemoved()) {
                    //
                }
            }
        });
        downloads.add(new Download("3847"));
        downloads.add(new Download("3567"));
        downloads.add(new Download("2357"));
    }

    private void addDownloads(List<? extends Download> downloads) {
        downloads.forEach(download -> {
            TreeItem<Download> treeItem = new TreeItem<>(download);
            $TreeDownloads.getRoot().getChildren().add(treeItem);
            new Thread(download::start).start();
        });
    }

    private void removeDownloads(List<? extends Download> downloads) {
        // remove treeitems from the treeview that hold these downloads
    }
}

下载.java

public class Download {

    private DoubleProperty progress = new SimpleDoubleProperty(0D);
    private StringProperty id = new SimpleStringProperty("");

    public Download(String id) {
        this.id.set(id);
    }

    public void start() {
        while (progress.getValue() < 1) {
            try {
                Thread.sleep(1000);
                progress.add(0.1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }      

    @Override
    public String toString() {
        return id.getValue();
    }
}

如何通过Object(Download)机制实现remove,有没有更简单的方法可以将observablelist的项目绑定到treeview?

【问题讨论】:

    标签: java javafx javafx-8 javafx-2


    【解决方案1】:

    仍然不能完全确定确切的问题是什么,都非常简单:

    首先,您的列表更改侦听器实现不正确,它必须在访问其状态之前推进 subChanges(您确实运行了发布的代码,或者没有;)

    downloads.addListener(new ListChangeListener<Download>() {
        @Override
        public void onChanged(Change<? extends Download> c) {
            // this while was missing
            while (c.next()) {
                if (c.wasAdded()) {
                    addDownloads(c.getAddedSubList());
                }
                if (c.wasRemoved()) {
                    // accessing the list of removed elements is .. plain standard api 
                    removeDownloads(c.getRemoved());
                }
    
            }
        }
    });
    

    现在实现对应treeItems的移除:

    private void removeDownloads(List<? extends Download> downloads) {
        // remove treeitems from the treeview that hold these downloads
        List<TreeItem<Download>> treeItemsToRemove = treeDownloads.getRoot().getChildren().stream()
                .filter(treeItem -> downloads.contains(treeItem.getValue()))
                .collect(Collectors.toList());
        treeDownloads.getRoot().getChildren().removeAll(treeItemsToRemove);
    }
    

    旁白:

    • java 命名约定对成员使用小写字母:treeDownloads(不是 $TreeDownloads)
    • MCVE 中的“可验证”意味着可以按原样运行:发帖人应该是第一个验证这一点的人;)你的不是由于监听器的错误实现
    • MCVE 中的“最小”意味着省略所有不需要的内容:f.i.调用线程代码 - 这在您的第一个 sn-p 中特别令人分心,因为违反 fx 的线程规则是一个相当常见的错误

    【讨论】:

    • 知道了,感谢您的解决方案和提示;) 至于我命名 treeview 变量的方式,这只是我的代码库的约定,所有 fxml ui 控件都以 $ControlName 开头。我发现它使调试更容易
    • @DarkMental 很公平——尽管您可能会考虑不在公共代码中使用这样的私有约定 :)
    • 有道理,从现在开始我会这样做,谢谢您的建议:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-06
    • 1970-01-01
    • 2013-05-25
    • 1970-01-01
    • 1970-01-01
    • 2016-10-14
    相关资源
    最近更新 更多