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:

everything working fine

after doubleclicks

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

Popular posts from this blog

javascript - AngularJS custom datepicker directive -

javascript - jQuery date picker - Disable dates after the selection from the first date picker -