JavaFX. GUI and model for read-only observable collection of observable collections -
i prepare gui in javafx , model (data provider) provides observable collection of observable collections of trading cards.
it nice if mentioned observable "parent" collection , every "child" collection outside model unmodifiable/read-only. every changes made inside model private methods.
let's trading card class looks this:
package cards; import javafx.scene.paint.color; public class tradingcard { private string title; private string subtitle; private color background; private color border; public tradingcard(string title, string subtitle, color background, color border) { this.title = title; this.subtitle = subtitle; this.background = background; this.border = border; } public string gettitle() { return title; } public string getsubtitle() { return subtitle; } public color getbackground() { return background; } public color getborder() { return border; } }
then prepare model provides collection of collections of trading cards readonlypropertylist.
package cards; import javafx.beans.property.readonlylistproperty; import javafx.beans.property.readonlylistwrapper; import javafx.collections.fxcollections; import javafx.collections.observablelist; import javafx.scene.paint.color; import java.util.arraylist; import java.util.list; public class model { private list<observablelist<tradingcard>> list; private observablelist<observablelist<tradingcard>> observablelist; private observablelist<observablelist<tradingcard>> unmodifiableobservablelist; private readonlylistwrapper<observablelist<tradingcard>> tradingcardswrapper; private list<observablelist<tradingcard>> modifiablelist; public model() { list = new arraylist<>(); observablelist = fxcollections.observablelist(list); unmodifiableobservablelist = fxcollections.unmodifiableobservablelist(observablelist); tradingcardswrapper = new readonlylistwrapper<>(unmodifiableobservablelist); // === modifiable list modifiablelist = new arraylist<>(); // === init examples // animals collection observablelist<tradingcard> tradingcardslist = createtradingcardscollection(); tradingcardslist.addall( new tradingcard("cat", "domestic cat", color.antiquewhite, color.black), new tradingcard("dog", "domestic dog", color.brown, color.saddlebrown) ); modifiablelist.add(tradingcardslist); observablelist.add(fxcollections.unmodifiableobservablelist(tradingcardslist)); // cars collection tradingcardslist = createtradingcardscollection(); tradingcardslist.addall( new tradingcard("458 mm", "ferrari 458 mm", color.blue, color.cadetblue), new tradingcard("cayman", "porsche cayman", color.honeydew, color.silver) ); modifiablelist.add(tradingcardslist); observablelist.add(fxcollections.unmodifiableobservablelist(tradingcardslist)); } public readonlylistproperty<observablelist<tradingcard>> tradingcardsproperty() { return tradingcardswrapper.getreadonlyproperty(); } public void manipulationmethod() { // === simulate model changes // add new toys collection observablelist<tradingcard> tradingcardslist = createtradingcardscollection(); tradingcardslist.addall( new tradingcard("train", "wooden train", color.honeydew, color.black), new tradingcard("cayman", "porsche cayman", color.brown, color.cornsilk) ); modifiablelist.add(tradingcardslist); observablelist.add(fxcollections.unmodifiableobservablelist(tradingcardslist)); // change animals collection (add , remove) tradingcardslist = modifiablelist.get(0); tradingcardslist.add(new tradingcard("dolphin", "maui's dolphin", color.aqua, color.deepskyblue)); tradingcardslist.remove(0); // remove cars collection observablelist.remove(1); modifiablelist.remove(1); } private observablelist<tradingcard> createtradingcardscollection() { list<tradingcard> templist = new arraylist<>(); observablelist<tradingcard> tempobservablelist = fxcollections.observablelist(templist); return tempobservablelist; } }
and gui (fxml):
<?import javafx.scene.layout.vbox?> <?import javafx.scene.control.button?> <?import javafx.scene.text.text?> <vbox fx:controller="cards.controller" xmlns:fx="http://javafx.com/fxml" spacing="20.0" alignment="center" > <text>collections:</text> <vbox fx:id="cardsvbox" spacing="10.0" /> <button text="manipulation method" onmouseclicked="#clicked" /> </vbox>
with controller:
package cards; import javafx.beans.property.readonlylistproperty; import javafx.collections.listchangelistener; import javafx.collections.observablelist; import javafx.fxml.fxml; import javafx.fxml.initializable; import javafx.scene.control.label; import javafx.scene.layout.hbox; import javafx.scene.layout.vbox; import javafx.scene.paint.color; import java.net.url; import java.util.resourcebundle; public class controller implements initializable { @fxml private vbox cardsvbox; private model model; public controller() { model = new model(); readonlylistproperty<observablelist<tradingcard>> tradingcardsproperty = model.tradingcardsproperty(); tradingcardsproperty.addlistener(new listchangelistener<observablelist<tradingcard>>() { @override public void onchanged(change<? extends observablelist<tradingcard>> c) { while(c.next()) { if (c.wasadded()) { (observablelist<tradingcard> tradingcardslist : c.getaddedsublist()) addcolection(tradingcardsproperty.indexof(tradingcardslist), tradingcardslist); } if (c.wasremoved()) { (observablelist<tradingcard> tradingcardslist : c.getremoved()) { // how index of element before removing? //removecollection(tradingcardsproperty.indexof(tradingcardslist)); } } } } }); } @override public void initialize(url location, resourcebundle resources) { readonlylistproperty<observablelist<tradingcard>> tradingcardsproperty = model.tradingcardsproperty(); int index = 0; (observablelist<tradingcard> tradingcardslist : tradingcardsproperty) addcolection(index++, tradingcardslist); } private void addcolection(int index, observablelist<tradingcard> tradingcardslist) { label label; hbox cardshbox = new hbox(20); (tradingcard card : tradingcardslist) { label = new label(card.gettitle() + ": " + card.getsubtitle()); label.setstyle("-fx-background-color:" + tohexcode(card.getbackground()) + ";-fx-border-width: 3;-fx-border-color:" + tohexcode(card.getborder())); cardshbox.getchildren().add(label); } cardsvbox.getchildren().add(index, cardshbox); } private void removecollection(int index) { cardsvbox.getchildren().remove(index); } @fxml private void clicked() { model.manipulationmethod(); } private static string tohexcode(color color ) { return string.format( "#%02x%02x%02x", (int)( color.getred() * 255 ), (int)( color.getgreen() * 255 ), (int)( color.getblue() * 255 ) ); } }
resume / questions
- is approach way how make unmodifibale/read-only collection of collections used outside model? there simplier/better approach? afraid recombined observable lists much.
- how index of element before removing (comment in controller)?
- how correctly handle changes inside "child" collections (adding/removing cards)?
permutations of cards inside collections prohibited.
Comments
Post a Comment