Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this possible that i can add context menu at TreeItem rather then TreeView in JavaFX

Tags:

javafx

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.

like image 670
Vikas Sharma Avatar asked Dec 19 '13 07:12

Vikas Sharma


People also ask

How to create a tree view in JavaFX?

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.

What is context menu in JavaFX?

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.

How do I access context menu?

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).


1 Answers

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();
}

}

like image 143
brian Avatar answered Sep 23 '22 09:09

brian