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:
- when cell not selected, has show
getbasicview()
ofperson
name
field. - when cell selected, has show
getexpandedview()
ofperson
multiline textname + "/n" + surname
.
what problem is?
the code wrote fills requirements given above additional bugs appeared:
- when adding new
person
blink of eye display of cells changestostring()
method not implemented (so user seessample.person@c4f324
alike trash).
- when removing
person
last cell weird things start happen. removedperson
name
remains in cell moves 2 cells down , because no longer containsperson
object - cannot cleared.
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
Post a Comment