2013-03-19 44 views
2

我正在使用Netbeans 7.2开发JavaFX 2.2应用程序。我正在使用树视图,并且我扩展了TreeCell以向每个treeItem提供一个带有“Collpase All”功能的MenuItem的上下文菜单。 Treeview的最大深度级别为4.当用户右键单击第2级的TreeItem并单击“Collapse All”MenuItem时,我想让所有第3级的TreeItems折叠(setExpanded(false))。下面你可以看到我使用的代码。我的问题是这个操作的内存和CPU成本。我插入了250个TreeItems到3级。所有操作崩溃的代价是每次崩溃时〜200MB的内存所有点击并花费大约2秒的时间!我的开发人员计算机CPU是intel i5(3.3GHz),我有8GB的内存。这是硬件成本正常或我在我的代码中做错了什么?我是否用错误的方式来折叠它们?手动展开/折叠所有treeitems内存成本javafx 2.2

该类管理TreeView。从数据库加载数据,重新加载数据,知道所选的TreeItem并展开/折叠选定的子TreeItems。

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 {

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> 

}

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

+0

为了更快得到更好的帮助,请发布SSCCE(http://sscce.org)。 – gontard 2013-03-19 10:13:10

回答

3

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

当我折叠展开的TreeItem然后updateItem方法将运行。这是内存和CPU成本的原因!我不得不折叠〜200个TreeItems,并且他们的父级扩展了。

我用一种非常简单的方法解决了我的问题。就在我开始折叠所有东西之前,我折叠了父TreeItem。因此,我第一次崩溃了父母,然后是所有的孩子。当孩子从源代码(setExpanded(false))一个接一个折叠起来时,updateItem方法没有运行,因为它们的父级,因此子级TreeItems不存在于屏幕中。

在这种方式下,我节省了大量的内存和CPU时间,我花了像一个假人。

+0

非常感谢你,今天我有一个很大的问题,在1000个项目的树视图.. :) – GOXR3PLUS 2017-09-17 17:23:38