java - ListView - how can I properly configure cell's display? -


i customize listview cell's display. assuming there's listview containing objects of person class , 2 buttons:

  • to add (generate) new person
  • to remove selected person

i'd achieve following goals:

  1. when cell not selected, has show getbasicview() of person name field.
  2. when cell selected, has show getexpandedview() of person multiline text name + "/n" + surname.

what problem is?

the code wrote fills requirements given above additional bugs appeared:

  1. when adding new person blink of eye display of cells changes tostring() method not implemented (so user sees sample.person@c4f324 alike trash).

bug no.1

  1. when removing person last cell weird things start happen. removed person name remains in cell moves 2 cells down , because no longer contains person object - cannot cleared.

bug no.2

i tried add listeners cells' itemproperty check if item null, after set text "" unfortunately not work. have idea how can make code functional?

providing sscce (assuming files in sample package):

main.java:

package sample;  import javafx.application.application; import javafx.fxml.fxmlloader; import javafx.scene.parent; import javafx.scene.scene; import javafx.stage.stage; import java.io.ioexception;  public class main extends application {    public void start(stage stage) {     fxmlloader fxmlloader = new fxmlloader();     fxmlloader.setcontroller(controller.class);     try {       parent parent = fxmlloader.load(getclass().getresource("/sample/sample.fxml"));       scene scene = new scene(parent);       stage.setscene(scene);       stage.show();     } catch (ioexception e) {       e.printstacktrace();     }   }    public static void main(string[] args) {     launch();   } } 

sample.fxml:

<?import javafx.scene.layout.hbox?> <?import javafx.scene.control.button?> <?import javafx.scene.control.listview?> <?import javafx.scene.layout.vbox?>  <hbox xmlns:fx="http://javafx.com/fxml" fx:controller="sample.controller">     <vbox>         <button text="add person" onaction="#addperson"/>         <button text="delete person" onaction="#deleteperson"/>     </vbox>     <listview prefheight="400" prefwidth="400" fx:id="listview"/> </hbox> 

controller.java:

package sample;  import javafx.application.platform; import javafx.collections.fxcollections; import javafx.collections.observablelist; import javafx.fxml.fxml; import javafx.scene.control.listview; import javafx.scene.control.multipleselectionmodel; import javafx.scene.control.cell.textfieldlistcell; import java.util.concurrent.threadlocalrandom;  public class controller {    @fxml   private listview<person> listview;   private observablelist<person> personlist = fxcollections.observablearraylist();   private string [] names = {"john", "katherine", "michael", "august", "peter"};   private string [] surnames = {"jones", "mayer", "stevens", "wayne", "milton"};    @fxml   private void initialize() {     initializelistcells();     initializelist();   }    private void initializelist() {     (int = 0 ; < 5 ; i++) {       personlist.add(generateperson());     }     listview.setitems(personlist);   }    private void initializelistcells() {     listview.setcellfactory(param -> {       textfieldlistcell<person> cell = new textfieldlistcell<person>();       cell.selectedproperty().addlistener((observable, oldvalue, newvalue) -> handlecelldisplaying(cell));       cell.itemproperty().addlistener((observable, oldvalue, newvalue) -> handlecelldisplaying(cell));       return cell;     });   }    private void handlecelldisplaying(textfieldlistcell<person> cell) {     person person = cell.getitem();     if (person != null) {       platform.runlater(() -> {         if (!cell.isselected()) {           cell.settext(person.getbasicview());         } else {           cell.settext(person.getexpandedview());         }       });     } else {       cell.settext("");     }   }    @fxml   private void addperson() {     personlist.add(generateperson());   }    @fxml   private void deleteperson() {     multipleselectionmodel<person> selectionmodel = listview.getselectionmodel();     if (!selectionmodel.isempty()) {       int selectedindex = selectionmodel.getselectedindex();       personlist.remove(selectedindex);     }   }    private person generateperson() {     int namerandom = threadlocalrandom.current().nextint(1,5);     int surnamerandom = threadlocalrandom.current().nextint(1,5);     return new person(names[namerandom],surnames[surnamerandom]);   } } 

person.java:

package sample;  public class person {   private string name;   private string surname;    public person(string name, string surname) {     this.name = name;     this.surname = surname;   }    public string getbasicview() {     return name;   }    public string getexpandedview() {     return name + "\n" + surname;   } } 

the problem textfieldlistcell implements cell lifecycle methods (updateitem, etc) , calls settext(item.tostring()) @ various points. interfering behavior trying implement. (for example, issue deleting last cell seems happen because settext("") called before textfieldlistcell resets text previous value. if use platform.runlater(...) hack surrounds complete if-else clause, problem goes away. however...)

if don't need cells editable, there no need use textfieldlistcell: use plain listcell. (also note there no need platform.runlater(...) in handler changed item/selected status.)

package sample;  import java.util.concurrent.threadlocalrandom;  import javafx.collections.fxcollections; import javafx.collections.observablelist; import javafx.fxml.fxml; import javafx.scene.control.listcell; import javafx.scene.control.listview; import javafx.scene.control.multipleselectionmodel;  public class controller {      @fxml     private listview<person> listview;     private observablelist<person> personlist = fxcollections.observablearraylist();     private string[] names = { "john", "katherine", "michael", "august", "peter" };     private string[] surnames = { "jones", "mayer", "stevens", "wayne", "milton" };      @fxml     private void initialize() {         initializelistcells();         initializelist();     }      private void initializelist() {         (int = 0; < 5; i++) {             personlist.add(generateperson());         }         listview.setitems(personlist);     }      private void initializelistcells() {         listview.setcellfactory(param -> {             listcell<person> cell = new listcell<person>();             cell.selectedproperty().addlistener((observable, oldvalue, newvalue) -> handlecelldisplaying(cell));             cell.itemproperty().addlistener((observable, oldvalue, newvalue) -> handlecelldisplaying(cell));             return cell;         });     }      private void handlecelldisplaying(listcell<person> cell) {         person person = cell.getitem();         if (person != null) {             if (!cell.isselected()) {                 cell.settext(person.getbasicview());             } else {                 cell.settext(person.getexpandedview());             }         } else {             cell.settext("");         }     }      @fxml     private void addperson() {         personlist.add(generateperson());     }      @fxml     private void deleteperson() {         multipleselectionmodel<person> selectionmodel = listview.getselectionmodel();         if (!selectionmodel.isempty()) {             int selectedindex = selectionmodel.getselectedindex();             personlist.remove(selectedindex);         }     }      private person generateperson() {         int namerandom = threadlocalrandom.current().nextint(1, 5);         int surnamerandom = threadlocalrandom.current().nextint(1, 5);         return new person(names[namerandom], surnames[surnamerandom]);     } } 

Comments

Popular posts from this blog

angular - Ionic slides - dynamically add slides before and after -

minify - Minimizing css files -

Add a dynamic header in angular 2 http provider -