栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

JavaFX:如何处理从TreeView拖动项目

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JavaFX:如何处理从TreeView拖动项目

您犯了过早优化的罪过:)。

TreeCell
基本上只为中的 当前可见
项创建
TreeView
。当您展开或折叠树中的节点时,或者在滚动时,这些
TreeCell
s被重用以显示不同的
TreeItem
s。这是
updateItem(...)
和中类似方法的目的
TreeCell
;当该
TreeCell
实例显示的项目更改时,将调用它们。

TreeCell
我的系统上的A 高约1/4英寸;要显示100,000
TreeCell
秒,将需要一台超过2,000英尺/
630米高的显示器。那时,您可能比一些额外的侦听器有更严重的内存分配问题…。但是无论如何,仅当特定单元格上发生事件时,才会调用侦听器,并且与单元本身,因此,除非您有任何直接的证据在单元上注册侦听器(如您所观察到的那样,可大大降低代码复杂性),否则会对性能产生不利影响,因此应使用“每个单元侦听器”方法。

这是一个树的示例,其中包含1,000,000个

Integer
值的树项。它跟踪
TreeCell
创建的s
的数量(在我的系统上,我设置的窗口大小似乎从未超过20)。它还显示一个标签。您可以将值从树中拖到标签上,标签将显示在那里滴下的所有值的总计。

import java.util.stream.IntStream;import javafx.application.Application;import javafx.beans.property.IntegerProperty;import javafx.beans.property.SimpleIntegerProperty;import javafx.concurrent.Task;import javafx.geometry.Insets;import javafx.geometry.Pos;import javafx.scene.Scene;import javafx.scene.control.Label;import javafx.scene.control.TreeCell;import javafx.scene.control.TreeItem;import javafx.scene.control.TreeView;import javafx.scene.input.ClipboardContent;import javafx.scene.input.DataFormat;import javafx.scene.input.Dragboard;import javafx.scene.input.TransferMode;import javafx.scene.layout.BorderPane;import javafx.stage.Stage;public class TreeViewNoSelection extends Application {    private static int cellCount =  0 ;    private final DataFormat objectDataFormat = new DataFormat("application/x-java-serialized-object");    @Override    public void start(Stage primaryStage) {        TreeView<Integer> tree = new TreeView<>();        tree.setShowRoot(false);        Task<TreeItem<Integer>> buildTreeTask = new Task<TreeItem<Integer>>() { @Override protected TreeItem<Integer> call() throws Exception {     TreeItem<Integer> treeRoot = new TreeItem<>(0);     IntStream.range(1, 10).mapToObj(this::createItem)         .forEach(treeRoot.getChildren()::add);     return treeRoot ; } private TreeItem<Integer> createItem(int value) {     TreeItem<Integer> item = new TreeItem<>(value);     if (value < 100_000) {         for (int i = 0; i < 10; i++) {  item.getChildren().add(createItem(value * 10 + i));         }     }     return item ; }        };        tree.setCellFactory(tv -> new TreeCell<Integer>() { {         System.out.println("Cells created: "+(++cellCount));     setonDragDetected(e -> {         if (! isEmpty()) {  Dragboard db = startDragAndDrop(TransferMode.COPY);  ClipboardContent cc = new ClipboardContent();  cc.put(objectDataFormat, getItem());  db.setContent(cc);  Label label = new Label(String.format("Add %,d", getItem()));  new Scene(label);  db.setDragView(label.snapshot(null, null));         }     }); } @Override public void updateItem(Integer value, boolean empty) {     super.updateItem(value, empty);     if (empty) {         setText(null);     } else {         setText(String.format("%,d", value));     } }        });        IntegerProperty total = new SimpleIntegerProperty();        Label label = new Label();        label.textProperty().bind(total.asString("Total: %,d"));        label.setonDragOver(e ->      e.acceptTransferModes(TransferMode.COPY));        // in real life use a CSS pseudoclass and external CSS file for the background:        label.setonDragEntered(e -> label.setStyle("-fx-background-color: yellow;"));        label.setonDragExited(e -> label.setStyle(""));        label.setonDragDropped(e -> { Dragboard db = e.getDragboard(); if (db.hasContent(objectDataFormat)) {     Integer value = (Integer) db.getContent(objectDataFormat);     total.set(total.get() + value);     e.setDropCompleted(true); }        });        BorderPane.setMargin(label, new Insets(10));        label.setMaxWidth(Double.MAX_VALUE);        label.setAlignment(Pos.CENTER);        BorderPane root = new BorderPane(new Label("Loading..."));        buildTreeTask.setonSucceeded(e -> { tree.setRoot(buildTreeTask.getValue()); root.setCenter(tree); root.setBottom(label);        });        primaryStage.setScene(new Scene(root, 250, 400));        primaryStage.show();        Thread t = new Thread(buildTreeTask);        t.setDaemon(true);        t.start();    }    public static void main(String[] args) {        launch(args);    }}

对于选择问题:我会问你为什么要这样做;这会带来不寻常的用户体验。问题可能在于,管理选择的“内置”事件处理程序在定义的处理程序之前被调用,因此在您使用该事件时,选择已被更改。您可以尝试添加事件过滤器:

cell.addEventFilter(MouseEvent.MOUSE_PRESSED, Event::consume);

但这也会禁用扩展/折叠树中的节点。

因此,您可以尝试以下操作:

cell.addEventFilter(MouseEvent.MOUSE_PRESSED, e -> {    if (getTreeItem() != null) {         Object target = e.getTarget();         if (target instanceof Node && ((Node)target).getStyleClass().contains("arrow")) {  getTreeItem().setExpanded(! getTreeItem().isExpanded());         }     }     e.consume();});

在这一点上,它开始看起来像是骇客。

如果要完全禁用选择,则另一个选择可能是为树创建自定义选择模型,该模型总是返回空选择。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/428335.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号