i am new to JavaFX. I made the custom TreeCell using this reference:-
http://fxexperience.com/2012/05/listview-custom-cell-factories-and-context-menus/
It perfectly worked for me. But my case is that i do not want to apply this context menu to child nodes. At start there is only single TreeItems and at later stage these TreeItems have child so the try to check isLeaf() method does not make a sense because at starting the TreeItems are at leaf level but later they become parent.
So any idea how can i achieve this.
Thanks a lot.
Update:
At initial stage of my project there is tree having three childs(mail service providers) as follows:-
---Gmail ---Yahoo ---Rediff
After i connect these providers then they have this structure:-
Gmail |____Inbox |____Sent Yahoo |___Inbox |___Sent |___Drafts Rediff |___Inbox
Now i want context menu only on Gmail,Yahoo and rediff and not on the inbox or sent item.
I know the setContextmenu() method but this is available for the TreeView and not for the TreeItem.
Creating Tree Views When you build a tree structure in your JavaFX applications, you typically need to instantiate the TreeView class, define several TreeItem objects, make one of the tree items the root, add the root to the tree view and other tree items to the root.
A context menu is a popup menu that appears on interacting with the UI elements in the application. The best example for this is the menu appears in your system when you right-click on the mouse. You can create a context menu by instantiating the javafx. scene.
A. Pressing Shift-F10 will bring up the context menu for any selected item. Just pressing F10 shifts the cursor focus to the first menu item (normally File).
I would make your tree items a descendant class of TreeItem like public class ProviderTreeItem extends TreeItem
and a different descendant with the boxes like BoxTreeItem.
That way you won't test for isLeaf but you can test the TreeItem type.
if (thisTreeItem.getClass() == ProviderTreeItem.class)
thisTreeItem.setContextmenu(providerContextMenu)
else thisTreeItem.setContextmenu(boxContextMenu)
It would be easier to just get the context menu from the subclassed TreeItem.
You don't really need to subclass TreeItem, you could just use the name or something like the userData object to distinguish between node types. If you subclass then you can add different methods and properties to the different node types.
For example the boxes will need a data structure to hold emails but the the providers don't need this. The providers need a web address and password etc., but the boxes don't need that.
Here's the updated example.
import javafx.application.Application;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Callback;
public class TVexample extends Application {
public abstract class AbstractTreeItem extends TreeItem{
public abstract ContextMenu getMenu();
}
public class ProviderTreeItem extends AbstractTreeItem{
// make class vars here like psswd
public ProviderTreeItem(String name) {
this.setValue(name);
}
@Override
public ContextMenu getMenu(){
MenuItem addInbox = new MenuItem("add inbox");
addInbox.setOnAction(new EventHandler() {
public void handle(Event t) {
BoxTreeItem newBox = new BoxTreeItem("inbox");
getChildren().add(newBox);
}
});
return new ContextMenu(addInbox);
}
}
public class BoxTreeItem extends AbstractTreeItem{
//private List<String> emails = new LinkedList<>();
public BoxTreeItem(String name) {
this.setValue(name);
}
@Override
public ContextMenu getMenu() {
return new ContextMenu(new MenuItem("test"));
}
}
private final class TreeCellImpl extends TreeCell<String> {
@Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText(null);
setGraphic(null);
} else {
setText(getItem() == null ? "" : getItem().toString());
setGraphic(getTreeItem().getGraphic());
setContextMenu(((AbstractTreeItem) getTreeItem()).getMenu());
}
}
}
@Override
public void start(Stage primaryStage) {
StackPane sceneRoot = new StackPane();
TreeItem treeRoot = new TreeItem();
treeRoot.setExpanded(true);
ProviderTreeItem gm = new ProviderTreeItem("gmail");
ProviderTreeItem yh = new ProviderTreeItem("yahoo");
treeRoot.getChildren().addAll(gm,yh);
TreeView<String> treeView = new TreeView<String>(treeRoot);
treeView.setShowRoot(false);
treeView.setCellFactory(new Callback<TreeView<String>,TreeCell<String>>(){
@Override
public TreeCell<String> call(TreeView<String> p) {
return new TreeCellImpl();
}
});
sceneRoot.getChildren().add(treeView);
Scene scene = new Scene(sceneRoot, 300, 500);
primaryStage.setScene(scene);
primaryStage.show();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With