gpt4 book ai didi

java - 手动展开/折叠所有 treeitems 内存成本 javafx 2.2

转载 作者:行者123 更新时间:2023-11-30 07:18:17 25 4
gpt4 key购买 nike

我正在使用 Netbeans 7.2 开发 JavaFX 2.2 应用程序。我正在使用 TreeView ,我扩展了 TreeCell 以向每个 TreeItem 提供一个上下文菜单,其中包含一个具有“Collpase All”功能的 MenuItem。 TreeView 的最大深度级别为 4。当用户右键单击级别 2 的 TreeItem 并单击“全部折叠”菜单项时,我想让级别 3 的所有 TreeItem 折叠(setExpanded(false))。您可以在下面看到我正在使用的代码。我的问题是此操作的内存和 CPU 成本。我在第 3 级插入了 250 个 TreeItems。每次折叠全部操作的成本是 ~200MB 内存,花费大约 2 秒的时间!我的开发者计算机的 CPU 是 Intel i5 (3.3GHz),我有 8GB 内存。这些硬件成本是正常的还是我的代码有问题?我是否使用了错误的方式来折叠它们?

这个类管理 TreeView。从数据库加载数据,重新加载它们,了解所选的 TreeItem 并展开/折叠所选的子 TreeItem。

public final class TargetTree extends SqlConnectionManager {

private TreeView tree;
private TreeItem selectedItem;

private TargetTree() {
super();
this.tree = null;
this.selectedItem = null;
}

private TargetTree(TreeView tree) {
super();
this.tree = tree;
this.selectedItem = null;
}

public static TargetTree construct(TreeView tree) {
if (tree == null) {
return null;
}

TargetTree targetTree = new TargetTree(tree);
targetTree.load();
return targetTree;
}

public void reload() {
// Clear current tree.
if (tree.getRoot() != null) {
for (int i = 0; i < tree.getRoot().getChildren().size(); i++) {
tree.getRoot().getChildren().clear();
}
tree.setRoot(null);
}
this.load();
}

public void prune() {
//TODO
}

private void load() {
// New root Item.
final TreeItem<Object> treeRoot = new TreeItem<>((Object) "Root");
treeRoot.setExpanded(true);

// This integers help to find when to build a new department/section/measure.
int lastDepartmentId = -1;
int lastSectionId = -1;
int lastMeasureId = -1;
int lastTargetId = -1;

//The temp treeitems.
TreeItem<Object> departmentTreeItem = null;
TreeItem<Object> sectionTreeItem = null;
TreeItem<Object> measureTreeItem = null;
TreeItem<Object> targetTreeItem = null;

// Get the new TreeItems from the database.
super.errorMessage = "";
try {
// Establishing connection with db.
super.openConnection();

// Query to be executed. Selects everything from the database.
preparedStmt = connection.prepareStatement(
"SELECT.....ORDER BY....;");
resultSet = preparedStmt.executeQuery();

while (resultSet.next()) {
// Department Creation.
if (lastDepartmentId != resultSet.getInt("departmentId")) {
final Department department = Department.initEmpty();
department.setId(resultSet.getInt("departmentId"));
department.setName(resultSet.getString("departmentName"));

// Create the treeitem for this department.
departmentTreeItem = new TreeItem<>((Object) department);
departmentTreeItem.setExpanded(true);
treeRoot.getChildren().add(departmentTreeItem);

// Reset the children ids to ensure that they will be recreated.
lastDepartmentId = resultSet.getInt("departmentId");
lastSectionId = -1;
lastMeasureId = -1;
lastTargetId = -1;
}

// Section Creation.
if (lastSectionId != resultSet.getInt("sectionId")) {
final Section section = Section.initEmpty();
section.setId(resultSet.getInt("sectionId"));
section.setName(resultSet.getString("sectionName"));

// Create the treeitem for this section.
sectionTreeItem = new TreeItem<>((Object) section);
sectionTreeItem.setExpanded(true);
departmentTreeItem.getChildren().add(sectionTreeItem);

// Reset the children ids to ensure that they will be recreated.
lastSectionId = resultSet.getInt("sectionId");
lastMeasureId = -1;
lastTargetId = -1;
}

// Measure Creation.
if (lastMeasureId != resultSet.getInt("measureId")) {
final Measure measure = Measure.initEmpty();
measure.setId(resultSet.getInt("measureId"));
measure.setLastname(resultSet.getString("measureLastname"));
measure.setFirstname(resultSet.getString("measureFirstName"));

// Create the treeitem for this measure.
measureTreeItem = new TreeItem<>((Object) measure);
measureTreeItem.setExpanded(true);
sectionTreeItem.getChildren().add(measureTreeItem );

// Reset the children ids to ensure that they will be recreated.
lastMeasureId = resultSet.getInt("measureId");
lastTargetId = -1;
}

// Target Creation.
if (lastTargetId != resultSet.getInt("targetId")) {
final Target target = Target.initEmpty();
target.setId(resultSet.getInt("targetId"));
target.setText(resultSet.getString("targetText"));

// Create the treeitem for this target.
targetTreeItem = new TreeItem<>((Object) target);
targetTreeItem.setExpanded(false);
measureTreeItem.getChildren().add(targetTreeItem);

// Reset the children ids to ensure that they will be recreated.
lastTargetId = resultSet.getInt("targetId");
}
}

closeAll();
} catch (SQLException ex) {
super.errorMessage = ex.getMessage();
}

tree.setRoot(treeRoot);
final TargetTree targetTree = this;
tree.setCellFactory(new Callback<TreeView<Object>, TreeCell<Object>>() {
@Override
public TreeCell<Object> call(TreeView<Object> p) {
return new TargetTreeCell(targetTree);
}
});

// Select a Tree Item.
tree.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() {
@Override
public void changed(ObservableValue observable, Object oldValue, Object newValue) {
selectedItem = (TreeItem) newValue;
}
});
}

public void collapseChildren() {
Thread thread = new Thread(new Task<Void>() {
@Override
protected Void call() throws Exception {
Platform.runLater(new Runnable() {
@Override
public void run() {
for (int i = 0; i < selectedItem.getChildren().size(); i++) {
TreeItem<Object> current = (TreeItem<Object>) selectedItem.getChildren().get(i);
if (!current.isLeaf()) {
current.setExpanded(false);
}
current = null;
}
selectedItem.setExpanded(false);
System.gc();
}
});
return null;
}
});
thread.setDaemon(true);
thread.start();
}

public void expandChildren() {
Thread thread = new Thread(new Task<Void>() {
@Override
protected Void call() throws Exception {
Platform.runLater(new Runnable() {
@Override
public void run() {
for (int i = 0; i < selectedItem.getChildren().size(); i++) {
TreeItem<Object> current = (TreeItem<Object>) selectedItem.getChildren().get(i);
if (!current.isLeaf()) {
current.setExpanded(true);
}
current = null;
}
selectedItem.setExpanded(true);
System.gc();
}
});
return null;
}
});
thread.setDaemon(true);
thread.start();
}
}

下面是自定义的 TreeCell 类。

public class TargetTreeCell extends TreeCell<Object> {

private TargetTree targetTree;

public TargetTreeCell(TargetTree targetTree) {
super();
this.targetTree = targetTree;
}

@Override
public void updateItem(Object item, boolean empty) {
super.updateItem(item, empty);

if (item != null) {
if (item instanceof Target) {
initTarget(item);
} else if (item instanceof Measure) {
initMeasure(item);
} else if (item instanceof Section) {
initSection(item);
} else if (item instanceof Department) {
initDepartment(item);
} else if (item instanceof String) {
initRoot(item);
}
}
}

///<editor-fold defaultstate="collapsed" desc="Tree Item Initialization">
private void initRoot(Object item) {
// Create Menu Items.
MenuItem expandAllMenuItems = new MenuItem("Expand All");
MenuItem collapseAllMenuItems = new MenuItem("Collapse All");

// Event Haddlers for each Menu Items.
expandAllMenuItems.setOnAction(new EventHandler() {
@Override
public void handle(Event event) {
}
});
collapseAllMenuItems.setOnAction(new EventHandler() {
@Override
public void handle(Event event) {
targetTree.collapseChildren();
}
});

// Create Menu and add Menu Items.
ContextMenu contextMenu = new ContextMenu();
contextMenu.getItems().addAll(expandAllMenuItems, collapseAllMenuItems);

//Init Root Tree Item.
String root = (String) item;
setText(root);
setContextMenu(contextMenu);
}

private void initDepartment(Object item) {
// Create Menu Items.
MenuItem expandAllMenuItems = new MenuItem("Expand All");
MenuItem collapseAllMenuItems = new MenuItem("Collapse All");

// Event Haddlers for each Menu Items.
expandAllMenuItems.setOnAction(new EventHandler() {
@Override
public void handle(Event event) {
targetTree.expandChildren();
}
});
collapseAllMenuItems.setOnAction(new EventHandler() {
@Override
public void handle(Event event) {
targetTree.collapseChildren();
}
});

// Create Menu and add Menu Items.
ContextMenu contextMenu = new ContextMenu();
contextMenu.getItems().addAll(expandAllMenuItems, collapseAllMenuItems);

//Init Department Tree Item.
Department department = (Department) item;
setText(department.getName());
setContextMenu(contextMenu);
}

private void initSection(Object item) {
// Create Menu Items.
MenuItem expandAllMenuItems = new MenuItem("Expand All");
MenuItem collapseAllMenuItems = new MenuItem("Collapse All");

// Event Haddlers for each Menu Items.
expandAllMenuItems.setOnAction(new EventHandler() {
@Override
public void handle(Event event) {
targetTree.expandChildren();
}
});
collapseAllMenuItems.setOnAction(new EventHandler() {
@Override
public void handle(Event event) {
targetTree.collapseChildren();
}
});

// Create Menu and add Menu Items.
ContextMenu contextMenu = new ContextMenu();
contextMenu.getItems().addAll(expandAllMenuItems, collapseAllMenuItems);

//Init Section Tree Item.
Section section = (Section) item;
setText(section.getName());
setContextMenu(contextMenu);
}

private void initMeasure(Object item) {
// Create Menu Items.
MenuItem expandAllMenuItems = new MenuItem("Expand");
MenuItem collapseAllMenuItems = new MenuItem("Collapse");

// Event Haddlers for each Menu Items.
expandAllMenuItems.setOnAction(new EventHandler() {
@Override
public void handle(Event event) {
targetTree.expandChildren();
}
});
collapseAllMenuItems.setOnAction(new EventHandler() {
@Override
public void handle(Event event) {
targetTree.collapseChildren();
}
});

// Create Menu and add Menu Items.
ContextMenu contextMenu = new ContextMenu();
contextMenu.getItems().addAll(expandAllMenuItems, collapseAllMenuItems);

//Init Section Tree Item.
Measure measure = (Measure) item;
setText(measure.getLastname() + " " + measure.getFirstname());
setContextMenu(contextMenu);
}

private void initTarget(Object item) {
//Init Section Tree Item.
Target target = (Target) item;
setText(target.getText());
}
///</editor-fold>
}

如果我有复制粘贴错误请原谅我..我编译没有问题。代码运行没有错误。我的问题出在第一类的方法 expandChildren() 和 collapseChildren() 上。在以前的版本中,我没有使用线程,而是使用递归来使所有子 TreeItems(及其子 TreeItems..)崩溃,但内存成本更高。

最佳答案

我找到了问题的答案!我将用一个例子来解释它。我用 100 个 TreeItems 初始化了一个 TreeView,结果是一个 3 层的树结构。在屏幕上,树只显示了其中的 45 个。要查看其他人,我必须向上/向下滚动或展开折叠的 TreeItems。在每种情况下,都会调用 updateItem 方法来构造新的 TreeItems,这些新的 TreeItems 将显示在屏幕树上可见,因此它们都出现在屏幕上。

当我折叠展开的 TreeItem 时,updateItem 方法将运行。这就是内存和 CPU 成本的原因!我不得不崩溃 ~ 200 个 TreeItems 就这样了,而且它们的父级展开了。

我用一种非常简单的方法解决了我的问题。就在我开始折叠所有内容之前,我折叠了父 TreeItem。因此,我首先折叠了 parent ,然后折叠了所有的 child 。当子项从源代码 (setExpanded(false)) 中一一折叠时,updateItem 方法未运行,因为屏幕中不存在它们的父项和子项 TreeItems。

通过这种方式,我节省了大量的内存和 CPU 时间,而这些时间我就像一个傻瓜一样花费。

关于java - 手动展开/折叠所有 treeitems 内存成本 javafx 2.2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15490268/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com