Tree View JavaFX Memory out of Space - java

I have created javaFX tree with custom Objects (SystemNode).
Tree Items has graphics: check-box and image icon which I have set through updateItems() method.
Whenever I expand or collapse Item in tree ,twice or thrice I get JAVA HEAP MEMORY OUT OF SPACE and whole UI hangs UP.
PS: updateItems() method is invoked every time I expand or collapse tree node
I have tried adding event handlers but they didn't work.
Can anyone give some solutions.
Here is how I set cellFactory :
treeView_technicalAreas.setCellFactory(Util.getTreeCellFactory());
Here is code for cell factory:
public static Callback<TreeView<SystemNode>, TreeCell<SystemNode>> getTreeCellFactory() {
Callback<TreeView<SystemNode>, TreeCell<SystemNode>> callback = new Callback<TreeView<SystemNode>, TreeCell<SystemNode>>() {
#Override
public TreeCell<SystemNode> call(TreeView<SystemNode> p) {
TreeCell<SystemNode> cell = new TreeCell<SystemNode>() {
#Override
protected void updateItem(SystemNode t, boolean isEmpty) {
super.updateItem(t, isEmpty); //To change body of generated methods, choose Tools | Templates.
if (!isEmpty) {
System.out.println("util call back : " + t.getSystem().getName());
setText(t.getSystem().getName());
HBox hBox = new HBox();
CheckBox checkBox = new CheckBox();
checkBox.setSelected(t.getSelected());
checkBox.selectedProperty().bindBidirectional(t.getSelectedProperty());
hBox.setSpacing(SPACING_BETWEEN_ICON_AND_CHECKBOX);
ImageView imageView_icon = null;
if (t.getSystem().getType() == TYPE.BAREA) {
imageView_icon = new ImageView(Constant.Image_AREAS);
} else if (t.getSystem().getType() == TYPE.AREA) {
imageView_icon = new ImageView(Constant.Image_AREAS);
} else if (t.getSystem().getType() == TYPE.DOCUMENT) {
imageView_icon = new ImageView(Constant.Image_DOCUMENTS);
} else if (t.getSystem().getType() == TYPE.NOUN_NAME) {
imageView_icon = new ImageView(Constant.Image_NOUN_NAME);
} else if (t.getSystem().getType() == TYPE.CHANGE) {
imageView_icon = new ImageView(Constant.Image_DCC);
} else if (t.getSystem().getType() == TYPE.TASK) {
imageView_icon = new ImageView(Constant.Image_TASK);
}
hBox.getChildren().addAll(checkBox, imageView_icon);
setGraphic(hBox);
}
}
};
return cell;
}
};
return callback;
}

Related

Initialize table column based on button click

I am fairly new in JavaFX. I have a table with multiple columns and two buttons (btnBuilding , btnBSearch) outside the table. In the table, I have a column colAction where I want to have some buttons based on the button clicked outside the table. Suppose if I click btnBuilding I want to have 2 button Save and Refresh in my colAction column and Whenever I click btnBSearch I want to have 2 button Edit and Add in my colAction column. Inside the initialize() I tried like below
colAction.setCellFactory(col -> {
Button SaveButton = new Button("Save");
Button AddButton = new Button("Add");
Button RefreshButton = new Button("Refresh");
Button EditButton = new Button("Edit");
HBox hbox = new HBox(5);
if(btnBSearch.isFocused())
hbox.getChildren().addAll(AddButton,EditButton);
else if(btnBuilding.isFocused())
hbox.getChildren().addAll(SaveButton,RefreshButton);
TableCell<ModelBrBuilding, ModelBrBuilding> cell = new TableCell<ModelBrBuilding, ModelBrBuilding>() {
#Override
//Updating with the number of row
public void updateItem(ModelBrBuilding building, boolean empty) {
super.updateItem(building, empty);
if (empty) {
setGraphic(null);
} else {
setGraphic(hbox);
}
}
};
EditButton.setOnAction((ActionEvent event)->{
});
RefreshButton.setOnAction(event->{
});
SaveButton.setOnAction((ActionEvent event) -> {
});
AddButton.setOnAction(event -> {
});
return cell ;
});
But the problem is whatever button I click I am always getting Add and Edit in my action column. How can I add different button in my column based on the button (resides outside the table) I click?
The cellFactory runs only once for each cell. You need to make sure the cell is updated the button outside of the table is clicked.
You could do this by creating a property that contains a factory for the graphics and listen to it.
public interface GraphicFactory<T> {
Node createGraphic();
void updateGraphic(Node graphic, T item);
}
public class ReplacableGraphicTableCell<S, T> extends TableCell<S, T> {
private final ChangeListener<GraphicFactory<T>> factoryListener = (o, oldValue, newValue) -> {
if (newValue == null || isEmpty()) {
setGraphic(null);
} else {
Node n = newValue.createGraphic();
newValue.updateGraphic(n, getItem());
setGraphic(n);
}
};
private final ObservableValue<GraphicFactory<T>> factory;
private ReplacableGraphicTableCell(ObservableValue<GraphicFactory<T>> factory) {
this.factory = factory;
factory.addListener(factoryListener);
}
public static <E, F> Callback<TableColumn<E, F>, TableCell<E, F>> forTableColumn(ObservableValue<GraphicFactory<F>> factory) {
if (factory == null) {
throw new IllegalArgumentException();
}
return column -> new ReplacableGraphicTableCell(factory);
}
#Override
protected void updateItem(T item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
} else {
GraphicFactory<T> fact = factory.getValue();
if (fact == null) {
setGraphic(null);
} else {
Node graphic = getGraphic();
if (graphic == null) {
graphic = fact.createGraphic();
setGraphic(graphic);
}
fact.updateGraphic(graphic, item);
}
}
}
}
final ObjectProperty<GraphicFactory<Item>> graphicFactory = new SimpleObjectProperty<>();
TableColumn<Item, Item> column = new TableColumn<>();
column.setCellValueFactory(cd -> new SimpleObjectProperty<>(cd.getValue()));
column.setCellFactory(ReplacableGraphicTableCell.forTableColumn(graphicFactory));
ToggleGroup tg = new ToggleGroup();
tg.selectedToggleProperty().addListener((o, oldValue, newValue) -> {
GraphicFactory<Item> factory = null;
if (newValue != null) {
factory = (GraphicFactory<Item>) newValue.getUserData();
}
graphicFactory.set(factory);
});
RadioButton rb = new RadioButton("Add/Edit");
rb.setUserData(new GraphicFactory<Item>() {
#Override
public Node createGraphic() {
Button add = new Button("Add");
Button edit = new Button("Edit");
HBox hbox = new HBox(add, edit);
add.setOnAction(evt -> {
System.out.println("Add " + hbox.getUserData());
});
edit.setOnAction(evt -> {
System.out.println("Edit " + hbox.getUserData());
});
return hbox;
}
#Override
public void updateGraphic(Node graphic, Item item) {
graphic.setUserData(item);
}
});
rb.setToggleGroup(tg);
RadioButton rb2 = new RadioButton("Save/Refresh");
rb2.setUserData(new GraphicFactory<Item>() {
#Override
public Node createGraphic() {
Button save = new Button("Save");
Button refresh = new Button("Refresh");
HBox hbox = new HBox(save, refresh);
save.setOnAction(evt -> {
System.out.println("Save " + hbox.getUserData());
});
refresh.setOnAction(evt -> {
System.out.println("Refresh " + hbox.getUserData());
});
return hbox;
}
#Override
public void updateGraphic(Node graphic, Item item) {
graphic.setUserData(item);
}
});
rb2.setToggleGroup(tg);
It will not work this way. To begin with, you need to process the btnBuilding and btnBSearch buttons. Which of the buttons is pressed must reflect in the table you are using. For this purpose, one feature can be created propert to reflect which of the two buttons is pressed.
BooleanProperty showSearch = new SimpleBooleanProperty(false);
...
btnBuilding.setOnAction(e -> showSearch.setValue(false));
btnBSearch.setOnAction(e -> showSearch.setValue(true));
Then, you link the colAction column to the value of the property.
colAction.setCellValueFactory(cdf -> showSearch);
In this situation, you can create CellFactory to create the dynamic content cell
colAction.setCellFactory(col -> {
return new TableCell<String, Boolean>() {
Button SaveButton = new Button("Save");
Button AddButton = new Button("Add");
Button RefreshButton = new Button("Refresh");
Button EditButton = new Button("Edit");
HBox hboxBuilding = new HBox(5);
HBox hboxSearch = new HBox(5);
{
hboxBuilding.getChildren().addAll(AddButton,EditButton);
hboxSearch.getChildren().addAll(SaveButton,RefreshButton);
}
#Override
protected void updateItem(Boolean item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
}
else {
setGraphic(item ? hboxBuilding : hboxSearch);
}
}
};
});

How can i get last ListCell in ListView?

I have started making a program in JavaFX where i have ListView with added functionality like editing, adding new items and deleting.I have managed to do most of the work but there is still a little more to do. So far i have added the deleting and editing functionality successfully but i have got a small problem with the adding functionality. I can still add new items to the ListView but i can't make it possible to edit the newly added item, because i need the ListCell the new item represents to start editing it. So my question is how can i get the ListCell of the new item in the ListView.
For this purpose here is my code:
private TextField textField;
ListCell<String> cell = this;
int i = 0;
boolean manually_selected = false;
public LanguageListCell(ListView<String> languages)
{
ContextMenu contextMenu = new ContextMenu();
cell.setEditable(true);
MenuItem editItem = new MenuItem();
editItem.textProperty().bind(Bindings.format("Edit \"%s\"", cell.itemProperty()));
editItem.setOnAction(event -> {
// The LanguageListCell class i want to put here...
cell.startEdit();
});
MenuItem addItem = new MenuItem("Add language");
addItem.setOnAction(new EventHandler<ActionEvent> () {
#Override
public void handle(ActionEvent ev)
{
i++;
String lang = "New Language " + i;
languages.getItems().add(lang);
if(i == 10)
{
addItem.setDisable(true);
}
languages.getSelectionModel().clearSelection();
languages.getSelectionModel().select(languages.getItems().size() - 1);
cell.setItem(languages.getSelectionModel().getSelectedItem());
manually_selected = true;
}
});
MenuItem deleteItem = new MenuItem();
deleteItem.textProperty().bind(Bindings.format("Delete \"%s\"", cell.itemProperty()));
deleteItem.setOnAction(new EventHandler<ActionEvent> () {
#Override
public void handle(ActionEvent ev)
{
if(languages.getSelectionModel().getSelectedItems().size() - 1 > 0)
{
if(i > 0)
{
i = (languages.getItems().size() - languages.getSelectionModel().getSelectedItems().size()) - 1;
}
/*for(String lang: languages.getSelectionModel().getSelectedItems())
{
languages.getItems().remove(lang);
}*/
ArrayList<String> delete_data = new ArrayList<String>(languages.getSelectionModel().getSelectedItems());
languages.getItems().removeAll(delete_data);
}
languages.getItems().remove(cell.getItem());
if(i > 0) i = 0;
}
});
contextMenu.setOnShowing(new EventHandler<WindowEvent>() {
#Override
public void handle(WindowEvent e) {
if(languages.getSelectionModel().getSelectedItems().size() - 1 > 0)
{
editItem.setDisable(true);
addItem.setDisable(true);
}
}
});
contextMenu.getItems().addAll(addItem, editItem, deleteItem);
cell.textProperty().bind(cell.itemProperty());
cell.emptyProperty().addListener((obs, wasEmpty, isNowEmpty) -> {
if (isNowEmpty) {
cell.setContextMenu(null);
} else {
cell.setContextMenu(contextMenu);
}
});
}

Search filter in Container Codename One

I'm trying to implement a search filter in my Container which contains a set of buttons.
Here's my code:
public void listMenu() {
Dialog loading = new InfiniteProgress().showInifiniteBlocking();
loading.show();
final Form listMenu = new Form("List Menu");
listMenu.setLayout(new BoxLayout(BoxLayout.Y_AXIS));
Container list = new Container();
list.setLayout(new BoxLayout(BoxLayout.Y_AXIS));
list.removeAll();
Button back = new Button("Back to Main Menu");
ParseQuery<ParseObject> query = ParseQuery.getQuery("mylist");
query.whereExists("Title");
List<ParseObject> results = null;
try {
Button btn = null;
results = query.find();
if(!results.isEmpty()) {
int index = 0;
int size = results.size();
for(;index < size;++index) {
list.add(btn = new Button(results.get(index).getString("Title")));
addListener(btn);
}
}
} catch (com.parse4cn1.ParseException e) {
Dialog.show("Err", "Server is not responding.", "OK", null);
}
listMenu.add(list);
listMenu.add(back);
listMenu.show();
loading.dispose();
back.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ev)
{
new StateMachine("/theme");
}
});
}
This code basically is querying data from the Database then setting its results into buttons then added to a Container. My question is how to implement a search filter to my Container? I've seen FilterProxyListModel<T> but not sure if ListModel<T> is compatible with Container. I'd appreciate to see an example of search filter implementation in my code.
FilterProxyListModel is for List which we don't recommend anymore. There is a full sample of searching a container here. It uses MultiButton but using Button would work just as well:
hi.getToolbar().addSearchCommand(e -> {
String text = (String)e.getSource();
if(text == null || text.length() == 0) {
// clear search
for(Component cmp : hi.getContentPane()) {
cmp.setHidden(false);
cmp.setVisible(true);
}
hi.getContentPane().animateLayout(150);
} else {
text = text.toLowerCase();
for(Component cmp : hi.getContentPane()) {
Button mb = (Button)cmp;
String line1 = mb.getText();
boolean show = line1 != null && line1.toLowerCase().indexOf(text) > -1;
mb.setHidden(!show);
mb.setVisible(show);
}
hi.getContentPane().animateLayout(150);
}
}, 4);

How to set icons in Tree Grid GXT(GWT) columns?

I am working on GWT app where I should change default icons in Tree Grid to icons from my own. In other cases, I can easily set icons but that is not the case when I have tree grid. When I have just default grid my code for set icon is like this:
Protected List<ColumnConfig> getColumns() {
List<ColumnConfig> columnConfigs = new ArrayList<ColumnConfig>();
ColumnConfig columnConfig = new ColumnConfig("status", MSGS.gridUserColumnHeaderStatus(), 50);
GridCellRenderer<GwtUser> setStatusIcon = new GridCellRenderer<GwtUser>() {
public String render(GwtUser gwtUser, String property, ColumnData config, int rowIndex, int colIndex, ListStore<GwtUser> deviceList, Grid<GwtUser> grid) {
KapuaIcon icon;
if (gwtUser.getStatusEnum() != null) {
switch (gwtUser.getStatusEnum()) {
case DISABLED:
icon = new KapuaIcon(IconSet.USER);
icon.setColor(Color.RED);
break;
case ENABLED:
icon = new KapuaIcon(IconSet.USER);
icon.setColor(Color.GREEN);
break;
default:
icon = new KapuaIcon(IconSet.USER);
icon.setColor(Color.GREY);
break;
}
} else {
icon = new KapuaIcon(IconSet.USER);
icon.setColor(Color.GREY);
}
return icon.getInlineHTML();
}
};
columnConfig.setRenderer(setStatusIcon);
columnConfig.setAlignment(HorizontalAlignment.CENTER);
columnConfig.setSortable(false);
columnConfigs.add(columnConfig);
But when I apply that on my Tree Grid then just first item have an icon, and I can't expand the grid. This is my current code for that Tree Grid
List<ColumnConfig> configs = new ArrayList<ColumnConfig>();
ColumnConfig column = new ColumnConfig("topicName", MSGS.topicInfoTableTopicHeader(), 150);
column.setRenderer(new TreeGridCellRenderer<GwtTopic>());
configs.add(column);
column = new ColumnConfig("timestamp", MSGS.topicInfoTableLastPostedHeader(), 150);
configs.add(column);
store = new TreeStore<GwtTopic>();
AsyncCallback<List<GwtTopic>> topicsCallback = new AsyncCallback<List<GwtTopic>>() {
#Override
public void onSuccess(List<GwtTopic> topics) {
store.add(topics, true);
topicInfoGrid.unmask();
}
#Override
public void onFailure(Throwable t) {
FailureHandler.handle(t);
topicInfoGrid.unmask();
}
};
dataService.findTopicsTree(currentSession.getSelectedAccount().getId(), topicsCallback);
topicInfoGrid = new TreeGrid<GwtTopic>(store, new ColumnModel(configs));
topicInfoGrid.setBorders(false);
topicInfoGrid.setStateful(false);
topicInfoGrid.setLoadMask(true);
topicInfoGrid.mask("Loading");
topicInfoGrid.setStripeRows(true);
topicInfoGrid.getView().setAutoFill(true);
topicInfoGrid.getView().setEmptyText(MSGS.topicInfoGridEmptyText());
topicInfoGrid.disableTextSelection(false);
How to change this code to be able to set my own icons?
You can use the setIconProvider method to change the icon of a leaf:
topicInfoGrid.setIconProvider(new IconProvider<GwtTopic>() {
#Override
public ImageResource getIcon(GwtTopic gwtTopic) {
GwtTopicType type = gwtTopic.getType();
if (type == GwtTopicType.Folder) {
if (topicInfoGrid.isExpanded(gwtTopic)) return new TopicInfoResources.Instance.iconFolderOpen();
else return TopicInfoResources.Instance.iconFolder();
}
return TopicInfoResources.Instance.user();
}
});
And this is your interface that extends ClientBundle:
public interface TopicInfoResources extends ClientBundle
{
public static final TopicInfoResources Instance = GWT.create(TopicInfoResources.class);
#Source("folder.png") ImageResource iconFolder();
#Source("folder-open.png") ImageResource iconFolderOpen();
#Source("user.png") ImageResource user();
}
Hope this helps!

Manually expand/collapse all treeitems memory cost javafx 2.2

I am developing a JavaFX 2.2 application using Netbeans 7.2. I am working with a treeview and I extended TreeCell to provide to each TreeItem a context-menu with a MenuItem with "Collpase All" functionality. The max depth level of the treeview is 4. When a user right clicks on a TreeItem of level 2 and clicks to "Collapse All" MenuItem i want to make all the TreeItems of level 3 collapsed (setExpanded(false)). Below you can see the code that I am using. My problem is the memory and CPU cost of this operation. I inserted 250 TreeItems to level 3. The cost of a collapse all operation was ~200MB of memory on each collapseAll click and spends about 2s of time! My developer computer's CPU is an Intel i5 (3.3GHz) and I have 8GB of memory. Is this numbers of hardware cost normal or I am doing something wrong in my code? Am I using a wrong way to collapse them?
This class manages the TreeView. Loads data from database, reloads them, knows the selected TreeItem and expand/collapse the selected children 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();
}
}
Below is the custom TreeCell class.
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>
}
If I have a copy-paste error please forgive me..I don't have problem with compiling. The code is running without errors. My problem is on the methods expandChildren() and collapseChildren() of the first class. In a previous version I didn't used threads and I used recursion to make all the children TreeItems (and their children TreeItems..) to collapse but the memory cost was more.
I found the answer to my problem! I will explain it with an example.
I initialize a TreeView with 100 TreeItems and the result is a tree structure with 3 levels.
On the screen the tree was displaying only 45 of them. To view the others i had to scroll up/down or to expand the collapsed TreeItems. On each case, the method updateItem is called to construct the new TreeItems that will appear to the visible on screen tree and therefore they all was appearing in the screen.
When i collapse an expanded TreeItem then the updateItem method will run. This was the reason of the memory and cpu cost! I had to collapse ~ 200 TreeItems that was all, and their parent expanded.
I solved my problem with a very simple way. Just before i started to collapse everything, i collapsed the parent TreeItem. Thus, i first collapsed the parent and then all the children. When the children was collapsed one by one from the source code (setExpanded(false)), the updateItem method was NOT running because their parent and therefore the children TreeItems was not existed in the screen.
On this way i saved a lot of memory and cpu time that i was spend like a dummy.
I did the same mistake,
happened as i implemented a MenuItem to collapse whole TreeItems (current selection as parent) child branches completely. But the collapse method clears the selection to minus one (-1) and that change wasn't visible because it didn't refreshed the parent item cell afterwards. So it seemed like nothing has changed at first sight because the focus was still visible on the same row.
I guess the skins selector needs to be cleared to do the collapse on child items, or taking over the selection index. so just collapse the parent item at first of which all child items should be folded and reset the selection index afterwards then unfold the parent item again.

Categories