treeview - ContextMenu in JavaFX keeps getting duplicates of the same MenuItem -
i use class give treeitem textfield editing (not relevant problem) , set contextmenu on treeitem:
package domain; import java.sql.connection; import java.sql.drivermanager; import java.sql.resultset; import java.sql.sqlexception; import java.sql.statement; import java.util.logging.level; import java.util.logging.logger; import javafx.event.actionevent; import javafx.event.eventhandler; import javafx.scene.control.contextmenu; import javafx.scene.control.menuitem; import javafx.scene.control.textfield; import javafx.scene.control.treecell; import javafx.scene.control.treeitem; import javafx.scene.input.keycode; import javafx.scene.input.keyevent; public final class textfieldtreecellimpl extends treecell<mynode> { private textfield textfield; private contextmenu cm = new contextmenu(); string olditem = ""; private connection connection; string url = "jdbc:sqlserver://localhost:1433;databasename=hogent1415_11"; string user = "sa"; string password = "root"; statement statement; public textfieldtreecellimpl() throws sqlexception { connection = drivermanager.getconnection(url, user, password); statement = connection.createstatement(); } @override public void startedit() { super.startedit(); if (textfield == null) { createtextfield(); } settext(null); setgraphic(textfield); textfield.selectall(); } @override public void canceledit() { super.canceledit(); settext((string) getitem().value); setgraphic(gettreeitem().getgraphic()); } @override public void updateitem(mynode item, boolean empty) { super.updateitem(item, empty); if (empty) { settext(null); setgraphic(null); } else { if (isediting()) { if (textfield != null) { textfield.settext(getstring()); } settext(null); setgraphic(textfield); } else { settext(getstring()); setgraphic(gettreeitem().getgraphic()); menuitem cmitem1 = new menuitem("add continent"); cmitem1.setonaction(new eventhandler<actionevent>() { @override public void handle(actionevent e) { system.out.println("geklikt!"); } }); cm.getitems().add(cmitem1); setcontextmenu(cm); } } } private void createtextfield() { textfield = new textfield(getstring()); textfield.setonkeyreleased(new eventhandler<keyevent>() { @override public void handle(keyevent t) { if (t.getcode() == keycode.enter) { string sql = "update continents set name='" + textfield.gettext() + "' continentid=" + getitemid(); if (getitem().iscountry()) { sql = "update countries set name='" + textfield.gettext() + "' countryid=" + getitemid(); } if (getitem().isclimatechart()) { sql = "update climatecharts set location='" + textfield.gettext() + "' climatechartid=" + getitemid(); } try { resultset result = statement.executequery(sql); } catch (sqlexception ex) { logger.getlogger(textfieldtreecellimpl.class.getname()).log(level.severe, null, ex); } commitedit(new mynode(textfield.gettext(), gettype(), getitemid())); } else if (t.getcode() == keycode.escape) { canceledit(); } } }); } private string getstring() { return getitem() == null ? "" : getitem().tostring(); } private string gettype() { return getitem() == null ? "" : getitem().type; } private int getitemid() { return getitem() == null ? null : getitem().id; } }
i instance class in controller class using following code:
selectiontreeview.seteditable(true); selectiontreeview.setcellfactory(new callback<treeview<mynode>, treecell<mynode>>() { @override public treecell<mynode> call(treeview<mynode> p) { try { return new textfieldtreecellimpl(); } catch (sqlexception ex) { logger.getlogger(mainpanel.class.getname()).log(level.severe, null, ex); } return null; } });
however when run program , right click on items works fine, if keep clicking more on other items there keep on getting items in contextmenu.
to narrow down, happens everytime double click on item.
check screenshots:
i know because ipdateitem keeps on getting called, how can prevent this?
every time updateitem(...)
called, add menu item again (and never remove it). each time cell reused, gets copy of menu item.
the efficient approach create menu item in constructor , pass context menu there. note event handler can access current item easily:
public textfieldtreecellimpl() throws sqlexception { connection = drivermanager.getconnection(url, user, password); statement = connection.createstatement(); menuitem cmitem1 = new menuitem("add continent"); cmitem1.setonaction(new eventhandler<actionevent>() { @override public void handle(actionevent e) { mynode item = getitem(); // ... system.out.println("geklikt!"); } }); cm.getitems().add(cmitem1); }
you want remove context menu empty cells:
@override public void updateitem(mynode item, boolean empty) { super.updateitem(item, empty); if (empty) { settext(null); setgraphic(null); setcontextmenu(null); } else { if (isediting()) { if (textfield != null) { textfield.settext(getstring()); } settext(null); setgraphic(textfield); } else { settext(getstring()); setgraphic(gettreeitem().getgraphic()); setcontextmenu(cm); } } }
you can configure menu items further in updateitem(...)
method if need, declaring them fields, e.g.
public final class textfieldtreecellimpl extends treecell<mynode> { private textfield textfield; private contextmenu cm = new contextmenu(); private menuitem cmitem1 ; // ... @override public void updateitem(mynode item, boolean empty) { super.updateitem(item, empty); // ... cmitem1.settext(...); } }
finally, if need restructure context menu when item changes, can do
@override public void updateitem(mynode item, boolean empty) { super.updateitem(item, empty); // ... cm.getitems().clear(); // create menu items scratch , add context menu }
Comments
Post a Comment