A big question still remains: Many have huge data models being populated from streaming XML files or a data storage such as Oracle or binary files, and now they want to bind them to JavaFX's cool and easy graphical interfaces.
How is that done? Are there interfaces to implement in order to make the "bind" keyword work? What about "inverse"? How will creation of such new items work, when discussing the JSON-type instantiation?
Expectations[]
Encapsulating Java classes in JavaFX UI classes[]
This is how I would expect it to look like:
class PersonUI extends CompositeNode { attribute x: Number; attribute y: Number; attribute person: Person; } operation PersonUI.composeNode() = Text { x: bind x y: bind y text: bind person.name }
Where Person is a Java class defined:
public class Person { private String name; public void setName(String name) { this.name = name; } public String getName() { return name; } }
Note that I'm not discussing yet how to let JavaFX know that a change has occured in "name", so surely binding to it will have no effect. Yet.
This is basically how it works, though I don't know how well JavaFX can detect the change of 'name' in the background either. Haven't tried that yet. If the data change is done entirely by the GUI, then it's not an issue.
The flaw in your example is your binding to person.name which bypasses your accessor method and tries to access a private instance variable. Won't work. Instead, your bind statement should read:
text: bind person.getName()
Since it's a bind via a method, I don't think that a background change of name would be detected without some sort of repaint of the Text instance. --Rcasey 21:47, 21 August 2007 (UTC)
XML[]
We can directly create XML-like nodes in jfx, like so:
import javafx.ui.*; /** * @author rjudson */ /** Shared stuff for XML Nodes. */ class XMLNode { attribute ns: String; attribute tag: String; attribute text: String; } /** XML attributes. */ class XMLAttr extends XMLNode { } /** XML elements. */ class XMLElem extends XMLNode { attribute attrs: XMLAttr*; attribute content: XMLElem*; function attr(name): String?; function elements(name): XMLElem*; function xpath(expr): XMLNode*; } function XMLElem.attr(name) { return attrs[a|a.tag == name].text; } function XMLElem.elements(name) { return select e from e in content where e.tag == name; } function XMLElem.xpath(expr) { // need xpath here :) return content; } // Examples of some functions that help create XML objects function vendor(name) { return XMLAttr{ tag: "vendor", text: name }; } function seller(name) { return XMLElem{ tag: "vendor", text: name }; } function book(bookname, code, sources) { return XMLElem{ tag: "book" attrs: [ XMLAttr{tag: "code", text: code}] text: bookname content: sources }; } function author(name) { return XMLElem{ tag: "author" text: name }; } class VBox extends Box { } attribute VBox.orientation = VERTICAL; class Space extends EmptyBorder {} attribute Space.bottom = 4; attribute Space.top = 4; attribute Space.left = 4; attribute Space.right = 4; var sampleData = XMLElem { tag: "books" attrs: [ vendor("A Publisher") ] content: [ book("Scary Blotter","sb12", [seller("GumBall")]), book("Golden Lumpiness", "sb13", [seller("GumBall")]), book("Panic Attack", "ph1", [seller("GumBall"), seller("Toast")]), book("Attacked by Panic", "ph2", [seller("GumBall"), seller("Toast")]), author("Ross Judson"), author("Chris Oliver") ] }; Frame { var datapath = bind sampleData var titleboxes = bind select Box { var vendorboxes = bind select Box { content: Label { text: "vendor: { datapath.text }" } } from datapath in datapath.elements("vendor") content: [ Label { text: "datapath.text}" }, vendorboxes, Button { text: "Remove {datapath.attr('code')}", mnemonic: R } ] } from datapath in datapath.elements("book") var anumber = 14 content: VBox { border: Space content: [ Label { text: "XML Data Nodes" font: Font { faceName: "Lucida Sans" size: anumber } }, titleboxes ] } }