Last active
December 19, 2015 10:58
-
-
Save ytoshima/5943940 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Small utility script to use JavaFX 2 from scala REPL | |
* To use ':l fxutil.scala' in REPL. | |
* Recent java7 JDK contains javafx runtime at $JAVA_HOME/jre/lib/jfxrt.jar | |
* Scala 2.9 takes -cp or CLASSPATH, so specify the jfxrt.jar path using | |
* either way. | |
* Scala 2.10 does not work in the same way. Its startup script passes | |
* -classpath "", thus -cp does not work. Instead, it has -toolcp option, | |
* so specify the jfxrt.jar using the option. | |
* | |
* JavaFX2 app usually extends javafx.application.Application class, | |
* implements start(Stage) method and calls Application.launch. The launch | |
* method initializes JavaFX runtime and calls back start method on JavaFX | |
* thread. | |
* | |
* runfx function takes code block and exexute the block on FX thread. | |
* operations like Stage or Scene instantiation needs to be done on FX thread. | |
* Otherwise, "IllegalStateException: Not on FX application thread" is thrown. | |
* | |
* runfx: (f: => Unit)Unit | |
* | |
* Another utility function is getStage. It takes a parent (or root) of the | |
* scene in the Stage. width and height are optional. | |
* | |
* getStage: (parent: javafx.scene.Parent, width: Int, height: Int)javafx.stage.Stage | |
* | |
* getStage create a Scene using parent as the root node, then create Stage | |
* with the Scene and returns the Stage. | |
* | |
* FxObj object provides some functions, some of them returns Nodes and others | |
* return a Stage. For example, getText2 returns a Text node. | |
* helloWorldButton returns a Stage which contains a Button. In most cases, | |
* functions which return a Stage calls show on it. | |
* | |
*/ | |
import javafx.application._ | |
import javafx.event._ | |
import javafx.scene._ | |
import javafx.scene.shape._ | |
import javafx.scene.control._ | |
import javafx.scene.layout._ | |
import javafx.scene.text._ | |
import javafx.stage._ | |
import javafx.scene.paint._ | |
import javafx.scene.effect._ // DropShadow etc | |
import javafx.scene.image._ // Image, ImageView | |
import javafx.geometry._ // Pos, Orientation, etc | |
import javafx.scene.input.MouseEvent | |
object FxUtil { | |
var stage: Stage = null | |
} | |
def fxinit { | |
import java.util.concurrent._ | |
new javax.swing.JWindow | |
val latch = new CountDownLatch(1) | |
import javafx.embed.swing._ | |
javax.swing.SwingUtilities.invokeLater( | |
new Runnable() { | |
def run() { | |
new JFXPanel() | |
latch.countDown | |
} | |
} | |
) | |
latch.await | |
println("fxinit done.") | |
} | |
def runfx(f: => Unit) { | |
Platform.runLater(new Runnable(){ | |
def run() { | |
f | |
} | |
}) | |
} | |
def runfxWait(f: => Unit) { | |
import java.util.concurrent._ | |
val latch = new CountDownLatch(1) | |
Platform.runLater(new Runnable(){ | |
def run() { | |
f | |
latch.countDown | |
} | |
}) | |
latch.await | |
} | |
def getStage(parent: Parent, width: Int = 0, height: Int = 0, depthBuffer: Boolean = false): Stage = { | |
val latch = new java.util.concurrent.CountDownLatch(1) | |
def sinit = { | |
val sb = StageBuilder.create | |
val scene = if (width == 0 && height == 0) new Scene(parent) | |
else new Scene(parent, width, height) | |
sb.scene(scene) | |
FxUtil.stage = sb.build() | |
FxUtil.stage.setScene(scene) | |
FxUtil.stage.sizeToScene() | |
latch.countDown | |
} | |
runfx(sinit) | |
latch.await | |
FxUtil.stage | |
} | |
def simpleButtonPane(textStr: String = "default string"): Parent = { | |
val root = new StackPane | |
val b = new Button | |
b.setText(textStr) | |
root.getChildren.add(b) | |
root | |
} | |
def getRuntimeName: String = | |
java.lang.management.ManagementFactory.getRuntimeMXBean.getName | |
def getpid: String = { | |
val namePtn = """(\d+)@.*""".r | |
getRuntimeName match { | |
case namePtn(pidStr) => pidStr | |
case other => other + "(not in expected format)" | |
} | |
} | |
/* // BeanProperty is from 2.10 ? | |
import scala.beans.BeanProperty | |
case class Person(@BeanProperty var firstName: String, | |
@BeanProperty var lastName: String, | |
@BeanProperty var email: String) { | |
def this() = this("","","") | |
} | |
*/ | |
case class Person(var firstName: String, | |
var lastName: String, | |
var email: String) { | |
def this() = this("","","") | |
def getFirstName = firstName | |
def setFirstName(s: String) { firstName = s } | |
def getLastName = lastName | |
def setLastName(s: String) { lastName = s } | |
def getEmail = email | |
def setEmail(s: String) { email = s } | |
} | |
import javafx.beans.property.SimpleStringProperty | |
case class Employee(sname: String, | |
sdepartment: String) { | |
val name = new SimpleStringProperty(sname) | |
val department = new SimpleStringProperty(sdepartment) | |
def getName = name.get | |
def setName(fName: String) { name.set(fName) } | |
def getDepartment = department.get | |
def setDepartment(fName: String) { department.set(fName) } | |
} | |
/* | |
class Person(fName: String, lName: String, em: String) { | |
@BeanProperty var firstName: String = fName | |
@BeanProperty var lastName: String = lName | |
@BeanProperty var email: String = em | |
} | |
*/ | |
object FxObj { | |
def getText2 = { | |
val t2 = new Text(50,50, "JavaFX 2.0") | |
val serif = Font.font("Serif", 30) | |
t2.setFont(serif) | |
t2.setFill(Color.RED) | |
val ds = new DropShadow | |
ds.setOffsetX(2.0f) | |
ds.setOffsetY(2.0f) | |
ds.setColor(Color.rgb(50,50,50,.588)) | |
t2.setEffect(ds) | |
t2 | |
} | |
def getText3 = { | |
val t = new Text(50,100,"JavaFX 2.0...") | |
val sanSerif = Font.font("SanSerif", 30) | |
t.setFont(sanSerif) | |
t.setFill(Color.BLUE) | |
t | |
} | |
def helloWorldButton: Stage = { | |
val root = new Group | |
val b = new Button | |
b.setLayoutX(100) | |
b.setLayoutY(80) | |
b.setText("Hello World") | |
b.setOnAction(new EventHandler[ActionEvent] { | |
def handle(event: ActionEvent) { | |
println("Hello World") | |
} | |
}) | |
root.getChildren().add(b) | |
val st = getStage(root, 300, 250) | |
runfx{st.show} | |
st | |
} | |
def drawingText: Stage = { | |
import java.util.Random | |
val root = new Group | |
val rand = new Random(System.currentTimeMillis()) | |
val (width, height) = (300, 250) | |
for (i <- 0 until 100) { | |
val (x, y) = (rand.nextInt(width), rand.nextInt(height)) | |
val (red, green, blue) = (rand.nextInt(255), rand.nextInt(255), rand.nextInt(255)) | |
val text = new Text(x, y, "JavaFX 2.0") | |
val rot = rand.nextInt(360) | |
text.setFill(Color.rgb(red, green, blue, .99)) | |
text.setRotate(rot) | |
root.getChildren().add(text) | |
} | |
val st = getStage(root, width, height) | |
runfx{st.show} | |
st | |
} | |
def fancyLabel: Stage = { | |
val root = new Group | |
val l = new Label("A label that needs to be wrapped") | |
l.setWrapText(true) | |
//l.setLayoutX(100) | |
//l.setLayoutY(80) | |
l.setFont(new Font("Cambria", 32)) | |
l.setRotate(315) | |
l.setTranslateX(50) | |
l.setTranslateY(10) | |
l.setPrefWidth(100) | |
l.setOnMouseEntered(new EventHandler[MouseEvent] { | |
def handle(e: MouseEvent) { | |
l.setScaleX(1.5) | |
l.setScaleY(1.5) | |
} | |
}) | |
l.setOnMouseExited(new EventHandler[MouseEvent] { | |
def handle(e: MouseEvent) { | |
l.setScaleX(1) | |
l.setScaleY(1) | |
} | |
}) | |
root.getChildren().add(l) | |
val st = getStage(root, 300, 250) | |
runfx{st.show} | |
st | |
} | |
def fancyText = { | |
val root = new Group | |
val t = new Text("Stroke and Fill") | |
t.setStyle("-fx-font: 100px Tahoma; -fx-fill: linear-gradient(from 0% 0% to 100% 200%, repeat, aqua 0%, red 50%); -fx-stroke: black; -fx-stroke-width: 1;") | |
t.setTranslateY(100) | |
/* | |
val fp = new FlowPane(10,10) | |
fp.getChildren().add(t) | |
root.getChildren().add(fp) | |
*/ | |
root.getChildren().add(t) | |
//println("D: bounds in local: " + t.getBoundsInLocal.getWidth.toInt + "x" + t.getBoundsInLocal.getHeight.toInt) | |
// size at this line does not work | |
//val st = getStage(root, t.getBoundsInLocal.getWidth.toInt, t.getBoundsInLocal.getHeight.toInt) | |
val st = getStage(root) | |
runfx{st.show} | |
//println("D: bounds in local: " + t.getBoundsInLocal.getWidth.toInt + "x" + t.getBoundsInLocal.getHeight.toInt) | |
st | |
} | |
def blurText = { | |
val root = new Group | |
val vbox = new VBox(2) | |
def boxBlur(bwidth: Int) : Node = { | |
val t = new Text() | |
t.setText("Blurry Text!") | |
t.setFill(Color.RED) | |
t.setFont(Font.font("null", FontWeight.BOLD, 36)) | |
t.setX(10) | |
t.setY(40) | |
val bb = new BoxBlur() | |
bb.setWidth(bwidth) | |
bb.setHeight(bwidth) | |
bb.setIterations(3) | |
t.setEffect(bb) | |
t | |
} | |
vbox.getChildren().add(boxBlur(5)) | |
vbox.getChildren().add(boxBlur(10)) | |
root.getChildren().add(vbox) | |
val st = getStage(root) | |
runfx{st.show} | |
st | |
} | |
def motionBlurText = { | |
val root = new Group | |
val vbox = new VBox(2) | |
def mBlurText(radius: Float, angle: Float) : Node = { | |
val t = new Text() | |
t.setText("Motion Blur") | |
t.setFill(Color.RED) | |
t.setFont(Font.font("null", FontWeight.BOLD, 60)) | |
t.setX(20.0f) | |
t.setY(80.0f) | |
val mb = new MotionBlur() | |
mb.setRadius(radius) | |
mb.setAngle(angle) | |
t.setEffect(mb) | |
t | |
} | |
vbox.getChildren().add(mBlurText(15.0f, 45.0f)) | |
root.getChildren().add(vbox) | |
val st = getStage(root) | |
runfx{st.show} | |
st | |
} | |
def gaussianBlurText = { | |
val root = new Group | |
val vbox = new VBox(2) | |
def gBlurText() : Node = { | |
val t = new Text() | |
t.setText("Gaussian Blur") | |
t.setCache(true) | |
t.setFill(Color.RED) | |
t.setFont(Font.font("null", FontWeight.BOLD, 36)) | |
t.setX(10.0f) | |
t.setY(140.0f) | |
t.setEffect(new GaussianBlur()) | |
t | |
} | |
vbox.getChildren().add(gBlurText()) | |
root.getChildren().add(vbox) | |
val st = getStage(root) | |
runfx{st.show} | |
st | |
} | |
// http://docs.oracle.com/javafx/2/visual_effects/jfxpub-visual_effects.htm | |
def reflectionText = { | |
val root = new Group | |
val t = new Text() | |
t.setX(10.0f) | |
t.setY(50.0f) | |
t.setCache(true) | |
t.setText("Reflection in JavaFX..") | |
t.setFill(Color.RED) | |
t.setFont(Font.font("null", FontWeight.BOLD,30)) | |
val r = new Reflection() | |
r.setFraction(0.9) | |
t.setEffect(r) | |
//t.setTranslateY(400) | |
root.getChildren().add(t) | |
val st = getStage(root) | |
runfx{st.show} | |
st | |
} | |
def toggleButtonPane = { | |
import javafx.beans.value.ObservableValue | |
import javafx.beans.value.ChangeListener | |
val root = new VBox(8) | |
val tg = new ToggleGroup() | |
val rb1 = new RadioButton("Home") | |
rb1.setToggleGroup(tg) | |
rb1.setSelected(true) | |
val rb2 = new RadioButton("Calendar") | |
rb2.setToggleGroup(tg) | |
val rb3 = new RadioButton("Contacts") | |
rb3.setToggleGroup(tg) | |
List(rb1, rb2, rb3).map(b => b.setUserData(b.getText)) | |
println("D: rb3 user data: " + rb3.getUserData) | |
tg.selectedToggleProperty.addListener(new ChangeListener[Toggle] { | |
def changed(ov: ObservableValue[_ <: Toggle], old_toggle: Toggle, new_toggle: Toggle) { | |
println("D: toggle old: " + old_toggle.getUserData + " new: " + new_toggle.getUserData) | |
} | |
}) | |
root.getChildren().addAll(rb1, rb2, rb3) | |
val st = getStage(root) | |
runfx{st.show} | |
st | |
} | |
def choiceBoxPane = { | |
import javafx.beans.value.ObservableValue | |
import javafx.beans.value.ChangeListener | |
import javafx.collections.FXCollections | |
val greetingMap = Map("English" -> "Hello", "Francais" -> "Bonjour", "Japanese" -> "Konichiwa") | |
val karr: Array[String] = greetingMap.map(_._1).toArray | |
val varr: Array[String] = greetingMap.map(_._2).toArray | |
val label = new Label("<default>") | |
val cb = new ChoiceBox(FXCollections.observableArrayList(karr: _*)) | |
cb.getSelectionModel().selectedIndexProperty().addListener(new ChangeListener[Number] { | |
def changed(ov: ObservableValue[_ <: Number], value: Number, new_value: Number) { | |
val niv = new_value.intValue | |
if (niv >= 0 && niv < varr.size) { | |
label.setText(varr(niv)) | |
} | |
println("D: old val " + value + " new value " + new_value) | |
} | |
}) | |
val root = new HBox(8) | |
root.getChildren().addAll(cb, label) | |
val st = getStage(root) | |
runfx{cb.setTooltip(new Tooltip("Select the language"))} | |
runfx{st.show} | |
st | |
} | |
def textFieldPane = { | |
val grid = new GridPane | |
grid.setPadding(new Insets(10,10,10,10)) | |
grid.setVgap(5) | |
grid.setHgap(5) | |
val name = new TextField | |
name.setPromptText("Enter your first name.") | |
name.setPrefColumnCount(10) | |
name.getText() | |
GridPane.setConstraints(name, 0, 0) | |
grid.getChildren.add(name) | |
val lastName = new TextField | |
lastName.setPromptText("Enter your last name.") | |
GridPane.setConstraints(lastName, 0, 1) | |
grid.getChildren.add(lastName) | |
val comment = new TextField | |
comment.setPromptText("Enter your comment.") | |
GridPane.setConstraints(comment, 0, 2) | |
grid.getChildren.add(comment) | |
val submit = new Button("Submit") | |
GridPane.setConstraints(submit, 1, 0) | |
grid.getChildren.add(submit) | |
val clear = new Button("Clear") | |
GridPane.setConstraints(clear, 1, 1) | |
grid.getChildren.add(clear) | |
val label = new Label | |
GridPane.setConstraints(label, 0, 3) | |
GridPane.setColumnSpan(label, 2) | |
grid.getChildren.add(label) | |
submit.setOnAction(new EventHandler[ActionEvent] { | |
def handle(e: ActionEvent) { | |
if ((comment.getText != null && !comment.getText.isEmpty)) { | |
label.setText(name.getText + " " + lastName.getText + ", " | |
+ " Thank you for your comment!") | |
} else { label.setText("You have not left a comment.")} | |
} | |
}) | |
clear.setOnAction(new EventHandler[ActionEvent] { | |
def handle(e: ActionEvent) { | |
List(name, lastName, comment).map(_.clear) | |
label.setText("") | |
} | |
}) | |
val st = getStage(grid) | |
runfx{st.show} | |
st | |
} | |
def listViewPane = { | |
import javafx.collections.FXCollections | |
val root = new VBox(8) | |
val list = new ListView[String] | |
val items = FXCollections.observableArrayList("Single", "Double", "Suite", "Family App") | |
list.setItems(items) | |
list.setPrefWidth(100) | |
list.setPrefHeight(70) | |
val hlist = new ListView[String] | |
hlist.setOrientation(Orientation.HORIZONTAL) | |
hlist.setItems(items) | |
hlist.setPrefWidth(100) | |
hlist.setPrefHeight(70) | |
root.getChildren.addAll(list, hlist) | |
val st = getStage(root) | |
runfx{st.show} | |
st | |
} | |
def tableViewPane = { | |
val label = new Label("Address Book") | |
label.setFont(new Font("Arial", 20)) | |
val table = new TableView | |
table.setEditable(true) | |
val firstNameCol = new TableColumn("First Name") | |
val lastNameCol = new TableColumn("Last Name") | |
val emailCol = new TableColumn("Email") | |
table.getColumns.addAll(firstNameCol, lastNameCol, emailCol) | |
val vbox = new VBox | |
vbox.setSpacing(5) | |
vbox.setPadding(new Insets(10,0,0,10)) | |
vbox.getChildren.addAll(label, table) | |
val root = new Group | |
root.getChildren.addAll(vbox) | |
val st = getStage(root, 300, 500) | |
st.setTitle("Table View Sample") | |
runfx{st.show} | |
st | |
} | |
def tableSubColumn = { | |
val label = new Label("Address Book") | |
label.setFont(new Font("Arial", 20)) | |
val table = new TableView | |
table.setEditable(true) | |
val firstNameCol = new TableColumn("First Name") | |
val lastNameCol = new TableColumn("Last Name") | |
val emailCol = new TableColumn("Email") | |
emailCol.getColumns.addAll(new TableColumn("Primary"), new TableColumn("Secondary")) | |
table.getColumns.addAll(firstNameCol, lastNameCol, emailCol) | |
val vbox = new VBox | |
vbox.setSpacing(5) | |
vbox.setPadding(new Insets(10,0,0,10)) | |
vbox.getChildren.addAll(label, table) | |
val root = new Group | |
root.getChildren.addAll(vbox) | |
val st = getStage(root, 300, 500) | |
st.setTitle("Table View Sample") | |
runfx{st.show} | |
st | |
} | |
def tableDataPane = { | |
import javafx.collections.FXCollections | |
import javafx.scene.control.cell.PropertyValueFactory | |
val data = FXCollections.observableArrayList( | |
Person("Jacob", "Smith", "[email protected]"), | |
Person("Isabella", "Johnson", "[email protected]"), | |
Person("Ethan", "Williams", "[email protected]"), | |
Person("Emma", "Jones", "[email protected]"), | |
Person("Michael", "Brown", "[email protected]") | |
) | |
val label = new Label("Address Book") | |
label.setFont(new Font("Arial", 20)) | |
val table = new TableView[Person] | |
table.setEditable(true) | |
/* | |
val firstNameCol = new TableColumn("First Name") | |
val lastNameCol = new TableColumn("Last Name") | |
val emailCol = new TableColumn("Email") | |
*/ | |
val firstNameCol = new TableColumn[Person,String]("First Name") | |
val lastNameCol = new TableColumn[Person,String]("Last Name") | |
val emailCol = new TableColumn[Person,String]("Email") | |
firstNameCol.setMinWidth(100) | |
lastNameCol.setMinWidth(100) | |
emailCol.setMinWidth(100) | |
table.getColumns.addAll(firstNameCol, lastNameCol, emailCol) | |
firstNameCol.setCellValueFactory( | |
new PropertyValueFactory("firstName")) | |
lastNameCol.setCellValueFactory( | |
new PropertyValueFactory("lastName")) | |
emailCol.setCellValueFactory( | |
new PropertyValueFactory("email")) | |
/* | |
firstNameCol.setCellValueFactory( | |
new PropertyValueFactory[Person,String]("firstName")) | |
lastNameCol.setCellValueFactory( | |
new PropertyValueFactory[Person,String]("lastName")) | |
emailCol.setCellValueFactory( | |
new PropertyValueFactory[Person,String]("email")) | |
*/ | |
table.setEditable(true) | |
table.setItems(data) | |
val vbox = new VBox | |
vbox.setSpacing(5) | |
vbox.setPadding(new Insets(10,0,0,10)) | |
vbox.getChildren.addAll(label, table) | |
val root = new Group | |
root.getChildren.addAll(vbox) | |
val st = getStage(root, 300, 500) | |
st.setTitle("Table View Sample") | |
runfx{st.show} | |
st | |
} | |
def simpleTree = { | |
import java.io.FileInputStream | |
//val rootIcon = new ImageView(new Image(getClass().getResourceAsStream("folder-s.png"))) | |
val rootIcon = new ImageView(new Image(new FileInputStream("folder-s.png"))) | |
val rootItem = new TreeItem[String]("Inbox", rootIcon) | |
rootItem.setExpanded(true) | |
for (i <- 0 until 6) { | |
val item = new TreeItem[String]("Message" + 1) | |
rootItem.getChildren().add(item) | |
} | |
val tree = new TreeView[String](rootItem) | |
val root = new StackPane | |
root.getChildren.add(tree) | |
val st = getStage(root, 300, 250) | |
runfx{st.show} | |
st | |
} | |
// Tree with Cell Factory | |
def treeDataPane = { | |
import java.io.FileInputStream | |
import scala.collection.JavaConversions._ | |
val rootIcon = new ImageView(new Image(new FileInputStream("root.png"))) | |
val depIcon = new Image(new FileInputStream("department.png")) | |
val employees = List( | |
new Employee("Ethan Williams", "Sales Department"), | |
new Employee("Emma Jones", "Sales Department"), | |
new Employee("Michael Brown", "Sales Department"), | |
new Employee("Anna Black", "Sales Department"), | |
new Employee("Rodger York", "Sales Department"), | |
new Employee("Susan Collins", "Sales Department"), | |
new Employee("Mike Graham", "IT Support"), | |
new Employee("Judy Mayer", "IT Support"), | |
new Employee("Gregory Smith", "IT Support"), | |
new Employee("Jacob Smith", "Accounts Department"), | |
new Employee("Isabella Johnson", "Accounts Department")) | |
val rootNode = new TreeItem[String]("MyCompany Human Resources", rootIcon) | |
rootNode.setExpanded(true) | |
employees.foreach{ e => | |
val empLeaf = new TreeItem[String](e.getName) | |
if (rootNode.getChildren.exists(dn => dn.getValue.contentEquals(e.getDepartment))) { | |
rootNode.getChildren.filter(dn => dn.getValue.contentEquals(e.getDepartment)).head.getChildren.add(empLeaf) | |
} else { | |
val depNode = new TreeItem[String](e.getDepartment, new ImageView(depIcon)) | |
rootNode.getChildren.add(depNode) | |
depNode.getChildren.add(empLeaf) | |
} | |
} | |
val box = new VBox | |
val treeView = new TreeView[String](rootNode) | |
box.getChildren.add(treeView) | |
val st = getStage(box, 400, 300) | |
st.setTitle("Tree View Sample") | |
st.getScene.setFill(Color.LIGHTGRAY) | |
runfx{st.show} | |
st | |
} | |
def treeCellFactPane = { | |
import java.io.FileInputStream | |
import scala.collection.JavaConversions._ | |
import javafx.scene.input._ // KeyCode, KeyEvent | |
import javafx.util.Callback | |
class TextFieldTreeCellImpl extends TreeCell[String] { | |
var textField: TextField = _ | |
override def startEdit { | |
super.startEdit | |
if (textField == null) createTextField | |
setText(null) | |
setGraphic(textField) | |
textField.selectAll | |
} | |
override def cancelEdit { | |
super.cancelEdit | |
setText(getItem.asInstanceOf[String]) | |
setGraphic(getTreeItem.getGraphic) | |
} | |
override def updateItem(item: String, empty: Boolean) { | |
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) | |
} | |
} | |
} | |
private def createTextField { | |
textField = new TextField(getString) | |
textField.setOnKeyReleased(new EventHandler[KeyEvent] { | |
override def handle(t: KeyEvent) { | |
if (t.getCode == KeyCode.ENTER) { | |
commitEdit(textField.getText) | |
} else if (t.getCode == KeyCode.ESCAPE) { | |
cancelEdit | |
} | |
} | |
}) | |
} | |
private def getString = if (getItem == null) "" else getItem.toString | |
} | |
val rootIcon = new ImageView(new Image(new FileInputStream("root.png"))) | |
val depIcon = new Image(new FileInputStream("department.png")) | |
val employees = List( | |
new Employee("Ethan Williams", "Sales Department"), | |
new Employee("Emma Jones", "Sales Department"), | |
new Employee("Michael Brown", "Sales Department"), | |
new Employee("Anna Black", "Sales Department"), | |
new Employee("Rodger York", "Sales Department"), | |
new Employee("Susan Collins", "Sales Department"), | |
new Employee("Mike Graham", "IT Support"), | |
new Employee("Judy Mayer", "IT Support"), | |
new Employee("Gregory Smith", "IT Support"), | |
new Employee("Jacob Smith", "Accounts Department"), | |
new Employee("Isabella Johnson", "Accounts Department")) | |
val rootNode = new TreeItem[String]("MyCompany Human Resources", rootIcon) | |
rootNode.setExpanded(true) | |
employees.foreach{ e => | |
val empLeaf = new TreeItem[String](e.getName) | |
if (rootNode.getChildren.exists(dn => dn.getValue.contentEquals(e.getDepartment))) { | |
rootNode.getChildren.filter(dn => dn.getValue.contentEquals(e.getDepartment)).head.getChildren.add(empLeaf) | |
} else { | |
val depNode = new TreeItem[String](e.getDepartment, new ImageView(depIcon)) | |
rootNode.getChildren.add(depNode) | |
depNode.getChildren.add(empLeaf) | |
} | |
} | |
val box = new VBox | |
val treeView = new TreeView[String](rootNode) | |
treeView.setEditable(true) | |
treeView.setCellFactory(new Callback[TreeView[String], TreeCell[String]] { | |
override def call(p: TreeView[String]): TreeCell[String] = { | |
new TextFieldTreeCellImpl | |
} | |
}) | |
box.getChildren.add(treeView) | |
val st = getStage(box, 400, 300) | |
st.setTitle("Tree View Sample") | |
st.getScene.setFill(Color.LIGHTGRAY) | |
runfx{st.show} | |
st | |
} | |
// treeCellFactPane + popup menu | |
def treeCellFactMenuPane = { | |
import java.io.FileInputStream | |
import scala.collection.JavaConversions._ | |
import javafx.scene.input._ // KeyCode, KeyEvent | |
import javafx.util.Callback | |
class TextFieldTreeCellImpl extends TreeCell[String] { | |
private var textField: TextField = _ | |
private val addMenu = new ContextMenu | |
// additional codes for popup | |
private val addMenuItem = new MenuItem("Add Employee") | |
addMenu.getItems.add(addMenuItem) | |
addMenuItem.setOnAction(new EventHandler[ActionEvent] { | |
def handle(t: ActionEvent) { | |
val newEmployee = new TreeItem[String]("New Employee") | |
getTreeItem.getChildren.add(newEmployee) | |
} | |
}) | |
/* | |
// simple translation from java is not sufficient since EventHandler | |
// takes a type parameter. | |
addMenuItem.setOnAction(new EventHandler { | |
def handle(t: Event) { | |
val newEmployee = new TreeItem[String]("New Employee") | |
getTreeItem.getChildren.add(newEmployee) | |
} | |
}) */ | |
// additional codes for popup end | |
override def startEdit { | |
super.startEdit | |
if (textField == null) createTextField | |
setText(null) | |
setGraphic(textField) | |
textField.selectAll | |
} | |
override def cancelEdit { | |
super.cancelEdit | |
setText(getItem.asInstanceOf[String]) | |
setGraphic(getTreeItem.getGraphic) | |
} | |
override def updateItem(item: String, empty: Boolean) { | |
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) | |
// add popup as needed | |
if (!getTreeItem.isLeaf && getTreeItem.getParent != null) { | |
setContextMenu(addMenu) | |
} | |
} | |
} | |
} | |
private def createTextField { | |
textField = new TextField(getString) | |
textField.setOnKeyReleased(new EventHandler[KeyEvent] { | |
override def handle(t: KeyEvent) { | |
if (t.getCode == KeyCode.ENTER) { | |
commitEdit(textField.getText) | |
} else if (t.getCode == KeyCode.ESCAPE) { | |
cancelEdit | |
} | |
} | |
}) | |
} | |
private def getString = if (getItem == null) "" else getItem.toString | |
} | |
val rootIcon = new ImageView(new Image(new FileInputStream("root.png"))) | |
val depIcon = new Image(new FileInputStream("department.png")) | |
val employees = List( | |
new Employee("Ethan Williams", "Sales Department"), | |
new Employee("Emma Jones", "Sales Department"), | |
new Employee("Michael Brown", "Sales Department"), | |
new Employee("Anna Black", "Sales Department"), | |
new Employee("Rodger York", "Sales Department"), | |
new Employee("Susan Collins", "Sales Department"), | |
new Employee("Mike Graham", "IT Support"), | |
new Employee("Judy Mayer", "IT Support"), | |
new Employee("Gregory Smith", "IT Support"), | |
new Employee("Jacob Smith", "Accounts Department"), | |
new Employee("Isabella Johnson", "Accounts Department")) | |
val rootNode = new TreeItem[String]("MyCompany Human Resources", rootIcon) | |
rootNode.setExpanded(true) | |
employees.foreach{ e => | |
val empLeaf = new TreeItem[String](e.getName) | |
if (rootNode.getChildren.exists(dn => dn.getValue.contentEquals(e.getDepartment))) { | |
rootNode.getChildren.filter(dn => dn.getValue.contentEquals(e.getDepartment)).head.getChildren.add(empLeaf) | |
} else { | |
val depNode = new TreeItem[String](e.getDepartment, new ImageView(depIcon)) | |
rootNode.getChildren.add(depNode) | |
depNode.getChildren.add(empLeaf) | |
} | |
} | |
val box = new VBox | |
val treeView = new TreeView[String](rootNode) | |
treeView.setEditable(true) | |
treeView.setCellFactory(new Callback[TreeView[String], TreeCell[String]] { | |
override def call(p: TreeView[String]): TreeCell[String] = { | |
new TextFieldTreeCellImpl | |
} | |
}) | |
box.getChildren.add(treeView) | |
val st = getStage(box, 400, 300) | |
st.setTitle("Tree View Sample") | |
st.getScene.setFill(Color.LIGHTGRAY) | |
runfx{st.show} | |
st | |
} | |
// FX 2.2 provides following editors which are subclass of TreeCell: | |
// CheckBoxTreeCell, ChoiceBoxTreeCell, ComboBoxTreeCell, TextFieldTreeCell | |
// Here is a sample which uses CheckBoxTreeCell | |
def treeCellEditor = { | |
import javafx.scene.control.cell.CheckBoxTreeCell | |
val rootItem = new CheckBoxTreeItem[String]("View Source Files") | |
rootItem.setExpanded(true) | |
val tree = new TreeView(rootItem) | |
tree.setEditable(true) | |
//tree.setCellFactory(CheckBoxTreeCell[String].forTreeView) | |
tree.setCellFactory(CheckBoxTreeCell.forTreeView[String]) | |
for (i <- 0 until 8) { | |
val checkBoxTreeItem = new CheckBoxTreeItem[String]("Sample" + (i+1)) | |
rootItem.getChildren.add(checkBoxTreeItem) | |
} | |
tree.setRoot(rootItem) | |
tree.setShowRoot(true) | |
val root = new StackPane | |
root.getChildren.add(tree) | |
val st = getStage(root, 300, 250) | |
runfx{st.show} | |
st | |
} | |
def shapes: Stage = { | |
def getQuad(translateY: Double) = { | |
val qb = QuadCurveBuilder.create | |
qb.startX(50); qb.startY(50); qb.endX(150); qb.endY(150) | |
qb.controlX(125); qb.controlY(150) | |
qb.translateY(translateY) | |
qb.strokeWidth(3) | |
qb.stroke(Color.BLACK); qb.fill(Color.WHITE) | |
qb.build | |
} | |
def getBigCircle(translateY: Double) = { | |
val eb = EllipseBuilder.create | |
eb.centerX(100); eb.centerY(100) | |
eb.radiusX(50); eb.radiusY(75/2) | |
eb.translateY(translateY) | |
eb.strokeWidth(3); eb.stroke(Color.BLACK); eb.fill(Color.WHITE) | |
eb.build | |
} | |
def getSmallCircle = { | |
val eb = EllipseBuilder.create | |
eb.centerX(100); eb.centerY(100) | |
eb.radiusX(35/2); eb.radiusY(25/2) | |
eb.build | |
} | |
def getDonut(bigcircle: Ellipse, smallcircle: Ellipse, translateY: Double) = { | |
//val donut = Path.subtract(bigCircle, smallCircle) | |
val donut = Shape.subtract(bigcircle, smallcircle) | |
donut.setFill(Color.rgb(255, 200, 0)) | |
// add drop shadow | |
val dropShadow = new DropShadow | |
dropShadow.setOffsetX(2.0f) | |
dropShadow.setOffsetY(2.0f) | |
dropShadow.setColor(Color.rgb(50,50,50,.588)) | |
donut.setEffect(dropShadow) | |
donut.setTranslateY(translateY) | |
donut | |
} | |
val root = new Group | |
val (width, height) = (300, 500) | |
val ccb = CubicCurveBuilder.create() | |
ccb.startX(50); ccb.startY(75); ccb.controlX1(80); ccb.controlY1(-25) | |
ccb.controlX2(110); ccb.controlY2(175); ccb.endX(140); ccb.endY(75) | |
ccb.strokeType(StrokeType.CENTERED); ccb.strokeWidth(1) | |
ccb.stroke(Color.BLACK); ccb.strokeWidth(3); ccb.fill(Color.WHITE) | |
val cubicCurve = ccb.build() | |
val path = new Path | |
val moveTo = new MoveTo | |
moveTo.setX(50); moveTo.setY(150) | |
val quadCurveTo = new QuadCurveTo | |
quadCurveTo.setX(150); quadCurveTo.setX(150) | |
quadCurveTo.setControlX(150); quadCurveTo.setControlX(150) | |
val lineTo1 = new LineTo | |
lineTo1.setX(50); lineTo1.setY(150) | |
val lineTo2 = new LineTo | |
lineTo2.setX(100); lineTo2.setY(275) | |
val lineTo3 = new LineTo | |
lineTo3.setX(150); lineTo3.setY(150) | |
val pes = path.getElements | |
pes.add(moveTo); pes.add(quadCurveTo); | |
pes.add(lineTo1); pes.add(lineTo2); pes.add(lineTo3) | |
path.setTranslateY(30) | |
path.setStrokeWidth(3) | |
path.setStroke(Color.BLACK) | |
val quad = getQuad(path.getBoundsInParent().getMaxY()) | |
val bigCircle = getBigCircle(quad.getBoundsInParent().getMaxY()) | |
val smallCircle = getSmallCircle | |
val donut = getDonut(bigCircle, smallCircle, quad.getBoundsInParent().getMinY() + 30) | |
root.getChildren.addAll(cubicCurve, path, quad, donut) | |
val st = getStage(root, width, height) | |
runfx{st.show} | |
st | |
} | |
def menu: Stage = { | |
def getTools = { | |
def getMenuItem(text: String, selected: Boolean) = { | |
val cmib = CheckMenuItemBuilder.create | |
cmib.text(text) | |
cmib.selected(selected) | |
cmib.build | |
} | |
val tools = new Menu("Camera") | |
tools.getItems.add(getMenuItem("Show Camera 1", true)) | |
tools.getItems.add(getMenuItem("Show Camera 2", true)) | |
tools | |
} | |
def getAlarm = { | |
val alarm = new Menu("Alarm") | |
def getGroupMenuItem(text: String, toggleGroup: ToggleGroup, selected: Boolean) = { | |
val rmib = RadioMenuItemBuilder.create | |
rmib.toggleGroup(toggleGroup) | |
rmib.text(text) | |
rmib.selected(selected) | |
rmib.build | |
} | |
def getContingencyPlans = { | |
val m = new Menu("Contingent Plans") | |
List("Self Destruct in T minus 50", "Trun off the coffee machine", | |
"Run for your lives! ").foreach{ | |
l:String => m.getItems.add(new CheckMenuItem(l)) | |
} | |
m | |
} | |
val tGroup = new ToggleGroup | |
val soundAlarmItem = getGroupMenuItem("Sound Alarm", tGroup, false) | |
val stopAlarmItem = getGroupMenuItem("Sound Off", tGroup, true) | |
alarm.getItems().add(soundAlarmItem) | |
alarm.getItems().add(stopAlarmItem) | |
val contingencyPlans = getContingencyPlans | |
alarm.getItems().add(contingencyPlans) | |
alarm | |
} | |
val root = new Group | |
val (width, height) = (300, 250) | |
val menuBar = new MenuBar | |
val menu = new Menu("File") | |
List(new MenuItem("New"), new MenuItem("Save"), new SeparatorMenuItem, | |
new MenuItem("Exit")).map(menu.getItems.add(_)) | |
menuBar.getMenus.add(menu) | |
val tools = getTools | |
menuBar.getMenus.add(tools) | |
val alarm = getAlarm | |
menuBar.getMenus.add(alarm) | |
root.getChildren.add(menuBar) | |
val st = getStage(root, width, height) | |
menuBar.prefWidthProperty.bind(st.widthProperty) | |
runfx{st.show} | |
st | |
} | |
def splitView = { | |
val (width, height) = (300, 250) | |
// left and right split pane | |
val splitPane = new SplitPane | |
// bind prefs later | |
val leftArea = new VBox(/* spacing */ 10) | |
for (i <- 0 until 5) { | |
val rowBox = new HBox(20) | |
val leftText = { | |
val tb = TextBuilder.create | |
tb.text("Left " + i) | |
tb.translateX(20); tb.fill(Color.RED) | |
tb.font(Font.font(null, FontWeight.BOLD, 20)) | |
tb.build | |
} | |
rowBox.getChildren.add(leftText) | |
leftArea.getChildren.add(rowBox) | |
} | |
leftArea.setAlignment(Pos.CENTER) | |
// upper and lower split pane | |
val splitPane2 = new SplitPane | |
splitPane2.setOrientation(Orientation.VERTICAL) | |
val centerArea = new HBox | |
val iShadow = { | |
val isb = InnerShadowBuilder.create | |
isb.offsetX(3.5f) | |
isb.offsetY(3.5f) | |
isb.build | |
} | |
val upperRight = { | |
val tb = TextBuilder.create | |
tb.text("Upper Right") | |
tb.x(100); tb.y(50); tb.effect(iShadow); tb.fill(Color.LIME) | |
tb.font(Font.font(null, FontWeight.BOLD, 35)) | |
tb.translateY(50) | |
tb.build | |
} | |
centerArea.getChildren.add(upperRight) | |
val rightArea = new HBox | |
val lowerRight = { | |
val tb = TextBuilder.create | |
tb.text("Lower Right"); tb.x(100); tb.y(50) | |
tb.effect(iShadow); tb.fill(Color.RED) | |
tb.font(Font.font(null, FontWeight.BOLD, 35)) | |
tb.translateY(50) | |
tb.build | |
} | |
rightArea.getChildren.add(lowerRight) | |
splitPane2.getItems.add(centerArea) | |
splitPane2.getItems.add(rightArea) | |
splitPane.getItems().add(leftArea) | |
splitPane.getItems().add(splitPane2) | |
val dividers = splitPane.getDividers | |
for (i <- 0 until dividers.size()) { | |
dividers.get(i).setPosition((i+1.0)/3) | |
} | |
val hbox = new HBox | |
hbox.getChildren().add(splitPane) | |
val root = new Group | |
root.getChildren().add(hbox) | |
val st = getStage(root, width, height) | |
val sc = st.getScene | |
// set splitPanes properties using Scene#widthProperty and heightProperty | |
splitPane.prefWidthProperty().bind(sc.widthProperty) | |
splitPane.prefHeightProperty().bind(sc.heightProperty) | |
splitPane2.prefWidthProperty().bind(sc.widthProperty) | |
splitPane2.prefHeightProperty().bind(sc.heightProperty) | |
runfx{st.show} | |
st | |
} | |
def webView = { | |
import javafx.scene.web.WebEngine | |
import javafx.scene.web.WebView | |
import javafx.beans.value.ChangeListener | |
import javafx.beans.value.ObservableValue | |
import javafx.scene.layout.AnchorPane | |
val (width, height) = (640, 480) | |
var webView: WebView = null | |
runfxWait { webView = new WebView } | |
val webEngine = webView.getEngine | |
val defaultUrl = "http://www.yahoo.co.jp" | |
runfx{webEngine.load(defaultUrl)} | |
val locationField = new TextField(defaultUrl) | |
webEngine.locationProperty.addListener(new ChangeListener[String] { | |
def changed(observable: ObservableValue[_ <: String], oldValue: String, newValue: String) { | |
locationField.setText(newValue) | |
} | |
}) | |
val goAction = new EventHandler[ActionEvent] { | |
def handle(event: ActionEvent) { | |
runfx { | |
webEngine.load( | |
if (locationField.getText.startsWith("http://")) | |
locationField.getText | |
else | |
"http://" + locationField.getText | |
) | |
} | |
} | |
} | |
locationField.setOnAction(goAction) | |
val goButton = new Button("Go") | |
goButton.setDefaultButton(true) | |
goButton.setOnAction(goAction) | |
val hBox = new HBox(5) | |
hBox.getChildren.setAll(locationField, goButton) | |
HBox.setHgrow(locationField, Priority.ALWAYS) | |
val vBox = new VBox(5) | |
vBox.getChildren.setAll(hBox, webView) | |
VBox.setVgrow(webView, Priority.ALWAYS) | |
val root = new AnchorPane | |
AnchorPane.setTopAnchor(vBox, 10.0) | |
AnchorPane.setLeftAnchor(vBox, 0.0) | |
AnchorPane.setRightAnchor(vBox, 0.0) | |
AnchorPane.setBottomAnchor(vBox, 0.0) | |
root.getChildren().add(vBox) | |
val st = getStage(root, width, height) | |
val sc = st.getScene | |
runfx{st.show} | |
st | |
} | |
def cube = { | |
import javafx.scene.transform.Rotate | |
import javafx.scene.PerspectiveCamera | |
import javafx.scene.transform.Translate | |
import javafx.animation.Animation | |
import javafx.animation.KeyFrame | |
import javafx.animation.KeyValue | |
import javafx.animation.Timeline | |
import javafx.scene.shape.RectangleBuilder | |
import javafx.util.Duration | |
import javafx.beans.value.WritableValue | |
case class Cube(size: Double, color: Color, shade: Double) extends Group { | |
val rx = new Rotate(0, Rotate.X_AXIS) | |
val ry = new Rotate(0, Rotate.Y_AXIS) | |
val rz = new Rotate(0, Rotate.Z_AXIS) | |
getTransforms.addAll(rx, ry, rx) | |
getChildren.addAll( | |
{ val r = RectangleBuilder.create // back face | |
r.width(size); r.height(size) | |
r.fill(color.deriveColor(0.0, 1.0, (1 - 0.5*shade), 1.0)) | |
r.translateX(-0.5*size) | |
r.translateY(-0.5*size) | |
r.translateZ(-0.5*size) | |
r.build}, | |
{ val r = RectangleBuilder.create // bottom face | |
r.width(size); r.height(size) | |
r.fill(color.deriveColor(0.0, 1.0, (1 - 0.4*shade), 1.0)) | |
r.translateX(-0.5*size) | |
r.translateY(0) | |
r.translateY(0) | |
r.rotationAxis(Rotate.X_AXIS) | |
r.rotate(90) | |
r.build}, | |
{ val r = RectangleBuilder.create // right face | |
r.width(size); r.height(size) | |
r.fill(color.deriveColor(0.0, 1.0, (1 - 0.3*shade), 1.0)) | |
r.translateX(-1*size) | |
r.translateY(-0.5*size) | |
r.rotationAxis(Rotate.Y_AXIS) | |
r.rotate(90) | |
r.build}, | |
{ val r = RectangleBuilder.create // left face | |
r.width(size); r.height(size) | |
r.fill(color.deriveColor(0.0, 1.0, (1 - 0.2*shade), 1.0)) | |
r.translateX(0) | |
r.translateY(-0.5*size) | |
r.rotationAxis(Rotate.Y_AXIS) | |
r.rotate(90) | |
r.build}, | |
{ val r = RectangleBuilder.create // top face | |
r.width(size); r.height(size) | |
r.fill(color.deriveColor(0.0, 1.0, (1 - 0.1*shade), 1.0)) | |
r.translateX(-0.5*size) | |
r.translateY(-1*size) | |
r.rotationAxis(Rotate.X_AXIS) | |
r.rotate(90) | |
r.build}, | |
{ val r = RectangleBuilder.create // top face | |
r.width(size); r.height(size) | |
r.fill(color) | |
r.translateX(-0.5*size) | |
r.translateY(-0.5*size) | |
r.translateZ(-0.5*size) | |
r.build } | |
) | |
} | |
def getSampleWidth = 400.0 | |
def getSampleHeight = 150.0 | |
val (width, height) = (400, 150) | |
val animation = new Timeline | |
def create3dContent = { | |
val c = Cube(50, Color.RED, 1) | |
c.rx.setAngle(45) | |
c.ry.setAngle(45) | |
val c2 = Cube(50, Color.GREEN, 1) | |
c2.setTranslateX(100) | |
c2.rx.setAngle(45) | |
c2.ry.setAngle(45) | |
val c3 = Cube(50, Color.ORANGE, 1) | |
c3.setTranslateX(-100) | |
c3.rx.setAngle(45) | |
c3.ry.setAngle(45) | |
animation.getKeyFrames.addAll( | |
new KeyFrame(Duration.ZERO, | |
/* compile error. Needed a cast... | |
* Still something is wrong | |
*/ | |
new KeyValue(c.ry.angleProperty.asInstanceOf[WritableValue[Double]], 0d), | |
new KeyValue(c2.rx.angleProperty.asInstanceOf[WritableValue[Double]], 0d), | |
new KeyValue(c3.rz.angleProperty.asInstanceOf[WritableValue[Double]], 0d) | |
), | |
new KeyFrame(Duration.seconds(1), | |
new KeyValue(c.ry.angleProperty.asInstanceOf[WritableValue[Double]], 360d), | |
new KeyValue(c2.rx.angleProperty.asInstanceOf[WritableValue[Double]], 360d), | |
new KeyValue(c3.rz.angleProperty.asInstanceOf[WritableValue[Double]], 360d) | |
) | |
) | |
animation.setCycleCount(Animation.INDEFINITE) | |
new Group(c, c2, c3) | |
} | |
def play { animation.play } | |
val root = new Group | |
root.getChildren().add(create3dContent) | |
val st = getStage(root, width, height, true) | |
st.setResizable(false) | |
val sc = st.getScene | |
sc.setCamera(new PerspectiveCamera) | |
root.getTransforms.addAll( | |
new Translate(400/2, 150/2), | |
new Rotate(180, Rotate.X_AXIS)) | |
runfx{st.show} | |
play | |
st | |
} | |
def htmlEditor = { | |
import javafx.scene.web.HTMLEditor | |
def getHTMLEditor = { | |
var e: HTMLEditor = null | |
runfxWait{ e = new HTMLEditor } | |
e | |
} | |
val initialText = """<html><body>Lorem ipsum dolor sit amet, consectetur adipiscing elit. | |
Nam tortor felis, pulvinar in scelerisque cursus, pulvinar at ante. Nulla consequat | |
congue lectus in sodales. Nullam eu est a felis ornare bibendum et nec tellus. | |
Vivamus non metus tempus augue auctor ornare. Duis pulvinar justo ac purus adipiscing | |
pulvinar. Integer congue faucibus dapibus. Integer id nisl ut elit aliquam sagittis | |
gravida eu dolor. Etiam sit amet ipsum sem.</body></html>""" | |
val (width, height) = (500, 500) | |
val vRoot = new VBox | |
vRoot.setPadding(new Insets(8,8,8,8)) | |
vRoot.setSpacing(5) | |
var htmlEditor = getHTMLEditor | |
htmlEditor.setPrefSize(500, 245) | |
runfx {htmlEditor.setHtmlText(initialText)} | |
vRoot.getChildren.add(htmlEditor) | |
val htmlLabel = new Label | |
htmlLabel.setMaxWidth(500) | |
htmlLabel.setWrapText(true) | |
val scrollPane = new ScrollPane | |
scrollPane.getStyleClass.add("noboder-scroll-pane") | |
scrollPane.setContent(htmlLabel) | |
scrollPane.setFitToWidth(true) | |
scrollPane.setPrefHeight(180) | |
val showHTMLButton = new Button("Show the HTML below") | |
vRoot.setAlignment(Pos.CENTER) | |
showHTMLButton.setOnAction(new EventHandler[ActionEvent] { | |
def handle(arg0: ActionEvent) { | |
htmlLabel.setText(htmlEditor.getHtmlText()) | |
} | |
}) | |
vRoot.getChildren.addAll(showHTMLButton, scrollPane) | |
val root = new Group | |
root.getChildren().add(vRoot) | |
val st = getStage(root, width, height, true) | |
val sc = st.getScene | |
runfx{st.show} | |
st | |
} | |
def lineChart = { | |
import javafx.scene.chart._ | |
def createChart = { | |
val xAxis = new NumberAxis | |
val yAxis = new NumberAxis | |
val lc = new LineChart[Number, Number](xAxis, yAxis) | |
lc.setTitle("Basic LineChart") | |
xAxis.setLabel("X Axis") | |
yAxis.setLabel("Y Axis") | |
val series = new XYChart.Series[Number, Number] | |
series.setName("Data Series 1") | |
series.getData.add(new XYChart.Data[Number,Number](20d,50d)) | |
series.getData.add(new XYChart.Data[Number,Number](40d,80d)) | |
series.getData.add(new XYChart.Data[Number,Number](50d,90d)) | |
series.getData.add(new XYChart.Data[Number,Number](70d,30d)) | |
series.getData.add(new XYChart.Data[Number,Number](170d,122d)) | |
lc.getData.add(series) | |
lc | |
} | |
val (width, height) = (600, 500) | |
val root = new Group | |
root.getChildren().add(createChart) | |
val st = getStage(root, width, height) | |
val sc = st.getScene | |
runfx{st.show} | |
st | |
} | |
def pieChart = { | |
import javafx.collections.FXCollections | |
import javafx.scene.chart._ | |
def createChart = { | |
val pc = new PieChart(FXCollections.observableArrayList( | |
new PieChart.Data("Sun", 20), | |
new PieChart.Data("IBM", 12), | |
new PieChart.Data("HP", 25), | |
new PieChart.Data("Dell", 22), | |
new PieChart.Data("Apple", 30))) | |
pc.setId("BasicPie") | |
pc.setTitle("Pie Chart Example") | |
pc | |
} | |
val (width, height) = (600, 500) | |
val root = new Group | |
root.getChildren().add(createChart) | |
val st = getStage(root, width, height) | |
val sc = st.getScene | |
runfx{st.show} | |
st | |
} | |
def tiledButtons = { | |
val tp = new TilePane(8,8) | |
val nButtons = 40 | |
(0 until nButtons).map(_.toString).map(new Button(_)).foreach(tp.getChildren.add(_)) | |
val st = getStage(tp) | |
runfx{st.show} | |
st | |
} | |
def fadeRect = { | |
import javafx.animation.FadeTransition | |
import javafx.animation.Animation | |
import javafx.animation.Timeline | |
import javafx.util.Duration | |
val root = new StackPane | |
val brect = new Rectangle(0,0,200,200) | |
val rect1 = new Rectangle(20,20,180,180) | |
root.getChildren.add(brect) | |
root.getChildren.add(rect1) | |
rect1.setArcHeight(20) | |
rect1.setArcWidth(20) | |
rect1.setFill(Color.RED) | |
val ft = new FadeTransition(Duration.millis(3000), rect1) | |
ft.setFromValue(1.0) | |
ft.setToValue(0.1) | |
//ft.setCycleCount(Timeline.INDEFINITE) | |
ft.setCycleCount(Animation.INDEFINITE) | |
ft.setAutoReverse(true) | |
ft.play | |
val st = getStage(root) | |
runfx(st.show) | |
st | |
} | |
def pathTrans = { | |
import javafx.animation.Animation | |
import javafx.animation.PathTransition | |
import javafx.util.Duration | |
val root = new Group | |
val (width, height) = (400, 300) | |
val rectPath = new Rectangle(0,0,40,40) | |
rectPath.setArcHeight(10) | |
rectPath.setArcWidth(10) | |
rectPath.setFill(Color.ORANGE) | |
val path = new Path | |
path.getElements.add(new MoveTo(20,20)) | |
path.getElements.add(new CubicCurveTo(380,0, 380,120, 200, 120)) | |
path.getElements.add(new CubicCurveTo(0, 120, 0,240,380, 240)) | |
val pathTransition = new PathTransition | |
pathTransition.setPath(path) | |
pathTransition.setNode(rectPath) | |
pathTransition.setDuration(Duration.millis(10000)) | |
pathTransition.setOrientation(PathTransition.OrientationType.ORTHOGONAL_TO_TANGENT) | |
pathTransition.setCycleCount(Animation.INDEFINITE) | |
pathTransition.setAutoReverse(true) | |
pathTransition.play | |
root.getChildren.addAll(rectPath, path) | |
val st = getStage(root, width, height) | |
runfx(st.show) | |
st | |
} | |
def timelineAnim = { | |
import javafx.animation.Animation | |
import javafx.animation.PathTransition | |
import javafx.util.Duration | |
import javafx.animation.KeyFrame | |
import javafx.animation.KeyValue | |
import javafx.animation.Timeline | |
import javafx.beans.value.WritableValue | |
val root = new Group | |
val (width, height) = (400, 300) | |
val rectBasicTimeline = new Rectangle(100,50,100,50) | |
rectBasicTimeline.setFill(Color.RED) | |
val timeline = new Timeline | |
timeline.setCycleCount(Animation.INDEFINITE) | |
timeline.setAutoReverse(true) | |
val kv = new KeyValue(rectBasicTimeline.xProperty.asInstanceOf[WritableValue[Any]], 300) | |
val kf = new KeyFrame(Duration.millis(5000), kv) | |
timeline.getKeyFrames.add(kf) | |
timeline.play | |
root.getChildren.addAll(rectBasicTimeline) | |
val st = getStage(root, width, height) | |
runfx(st.show) | |
st | |
} | |
def tooltip = { | |
val b = new Button("hover over me") | |
runfx{b.setTooltip(new Tooltip("Tooltip for Button"))} | |
val st = getStage(b) | |
runfx{st.show} | |
st | |
} | |
/* | |
def image = { | |
val root = new Group | |
val (width, height) = (551, 400) | |
val currentImageView = new ImageView | |
currentImageView.setPreserveRatio(true) | |
val pictureRegion = new HBox | |
pictureRegion.getChildren.add(currentImageView) | |
root.getChildren.add(pictureRegion) | |
val st = getStage(root, width, height) | |
val sc = st.getScene | |
currentImageView.fitWidthProperty().bind(sc.widthProperty) | |
sc.setOnDragOver(new EventHandler[DragEvent] { | |
def handle(event: DragEvent) { | |
val db = event.getDragboard | |
if (db.hasFiles()) { | |
event.acceptTransferModes(TransferMode.COPY) | |
} else { | |
event.consume() | |
} | |
} | |
}) | |
sc.setOnDragDropped(new EventHandler[DragEvent] { | |
dev handle(event: DragEvent) { | |
val db = event.getDragboard | |
if (db.hasFiles()) { | |
} | |
} | |
}) | |
// this sample needs states like file path, etc... | |
// cannot implement with a simple function | |
runfx{st.getScene.setFill(Color.BLACK)} | |
runfx{st.show} | |
st | |
} | |
*/ | |
val availableFuncNames = Seq("getText2", "getText3", "helloWorldButton", | |
"drawingText", "fancyLabel", "fancyText", "blurText", "motionBlurText", | |
"gaussianBlurText", "reflectionText", "toggleButtonPane", "choiceBoxPane", | |
"textFieldPane", "listViewPane", "tableViewPane", "tableSubColumn", | |
"tableDataPane", "simpleTree", "treeDataPane", "treeCellFactPane", | |
"treeCellFactMenuPane", "treeCellEditor", "shapes", "menu", "splitView", | |
"webView", "cube", "htmlEditor", "lineChart", "pieChart", "tiledButtons", | |
"tooltip", "fadeRect", "pathTrans", "timelineAnim") | |
} | |
fxinit | |
println("FxObj funcs: " + FxObj.availableFuncNames.mkString(", ")) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
JAVA_OPTS=-verbose:gc | |
export JAVA_OPTS | |
jdkhome=$(/usr/libexec/java_home -v 1.7) | |
#scala -toolcp $jdkhome/jre/lib/jfxrt.jar -i fxutil.scala | |
#scala -cp $jdkhome/jre/lib/jfxrt.jar -i fxutil.scala | |
scala -cp $jdkhome/jre/lib/jfxrt.jar:. | |
echo "try :l fxutil.scala" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
set JAVA_OPTS=-verbose:gc | |
set jdkhome=C:\PROGRA~2\Java\jdk1.7.0_25 | |
scala -toolcp %jdkhome%\jre\lib\jfxrt.jar -i fxutil.scala |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment