Packages

  • package root

    Helper methods and classes to simplify ScalaFX use.

    Helper methods and classes to simplify ScalaFX use.

    Package org.scalafx.extras contains basic helper methods for running tasks on threads and showing messages.

    Package org.scalafx.extras.image contains image display component with scrolling and zooming.

    Package org.scalafx.extras.mvcfx contains classes for creating with UI components based on FXML.

    Definition Classes
    root
  • package org
    Definition Classes
    root
  • package scalafx
    Definition Classes
    org
  • package extras

    Helper methods for working with ScalaFX.

    Helper methods for working with ScalaFX.

    Definition Classes
    scalafx
  • package generic_pane
    Definition Classes
    extras
  • DefaultLastDirectoryHandler
  • DirectorySelectionField
  • FileSelectionField
  • GenericDialogFX
  • GenericPane
  • GenericPaneBase
  • LastDirectoryHandler
  • NumberTextField
  • Utils
  • package image
    Definition Classes
    extras
  • package mvcfx

    Package mvcfx helps in implementation of Model-View-Controller-like patters, we call it MVCfx.

    Package mvcfx helps in implementation of Model-View-Controller-like patters, we call it MVCfx. The pattern is build around use of views defined in FXML (the view), with binding to ScalaFX using ScalaFXML library.

    There are two cooperating classes ControllerFX for binding FXML to Scala code and ModelFX that contains logic for the component. An additional helper MVCfx class is provided to instantiate the ControllerFX and the corresponding ModelFX.

    The structure of the UI component is defined in a standard JavaFX FXML file. The Scala side of the FXML is in a class ControllerFX. Part of the ControllerFX is automatically generated by ScalaFXML macro, the rest can be customized as needed, including binding of the UI to appropriate parts of the component logic represented by the ModelFX. Use of the MVCfx is optional and primarily intended to simplify instantiation of the ControllerFX and the ModelFX.

    Below is an example using the classes in mvcfx. The code implements a simple Stop Watch. The complete code is in demos part of the ScalaFX Extras project.

    Note the recommended naming convention used: * StopWatch extends MVCfx * StopWatchModel extends ModelFX * StopWatchController extends ControllerFX * StopWatch.fxml the FXVM declaration of the view

    First we have the FXML definitions representing the structure of the user interface (org/scalafx/extras/mvcfx/stopwatch/StopWatch.fxml)

    <?import javafx.geometry.Insets?>
    <?import javafx.scene.control.*?>
    <?import javafx.scene.layout.BorderPane?>
    <?import javafx.scene.layout.HBox?>
    <?import javafx.scene.text.*?>
    <BorderPane xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1"
                fx:controller="org.scalafx.extras.mvcfx.stopwatch.StopWatchController">
        <bottom>
            <ButtonBar BorderPane.alignment="CENTER">
                <buttons>
                    <Button fx:id="startButton" mnemonicParsing="false" text="Start"/>
                    <Button fx:id="stopButton" mnemonicParsing="false" text="Stop"/>
                    <Button fx:id="resetButton" mnemonicParsing="false" text="Reset"/>
                </buttons>
            </ButtonBar>
        </bottom>
        <center>
            <HBox>
                <children>
                    <Label fx:id="minutesLabel" alignment="CENTER" contentDisplay="CENTER" text="99" textAlignment="CENTER"
                           BorderPane.alignment="CENTER">
                    </Label>
                    <Label text=":">
                    </Label>
                    <Label fx:id="secondsLabel" alignment="CENTER" contentDisplay="CENTER" text="99" textAlignment="CENTER">
                    </Label>
                    <Label text=".">
                    </Label>
                    <Label fx:id="fractionLabel" alignment="CENTER" contentDisplay="CENTER" text="99"
                           textAlignment="CENTER">
                    </Label>
                </children>
            </HBox>
        </center>
    </BorderPane>

    The ControllerFX creates connection of the FXML to Scala code and underlying ModelFX for the application logic. Note the @sfxml annotation and the constructor arguments corresponding to controls defined in FXML, like minutesLabel. The last argument to the constructor is the ModelFX. (org.scalafx.extras.mvcfx.stopwatch.StopWatchController)

    package org.scalafx.extras.mvcfx.stopwatch
    
    import org.scalafx.extras.mvcfx.ControllerFX
    
    import scalafx.Includes._
    import scalafx.scene.control.{Button, Label}
    import scalafxml.core.macros.sfxml
    
    @sfxml
    class StopWatchController(minutesLabel: Label,
                              secondsLabel: Label,
                              fractionLabel: Label,
                              startButton: Button,
                              stopButton: Button,
                              resetButton: Button,
                              model: StopWatchModel) extends ControllerFX {
    
      minutesLabel.text.value = format2d(model.minutes.longValue)
      model.minutes.onChange { (_, _, newValue) =>
        minutesLabel.text.value = format2d(newValue.longValue)
      }
      secondsLabel.text.value = format2d(model.seconds.longValue())
      model.seconds.onChange { (_, _, newValue) =>
        secondsLabel.text.value = format2d(newValue.longValue())
      }
      fractionLabel.text.value = format2d(model.secondFraction.longValue() / 10)
      model.secondFraction.onChange { (_, _, newValue) =>
        fractionLabel.text.value = format2d(newValue.longValue() / 10)
      }
    
      startButton.disable <== model.running
      stopButton.disable <== !model.running
      resetButton.disable <== model.running
    
      startButton.onAction = handle {
        model.onStart()
      }
      stopButton.onAction = handle {
        model.onStop()
      }
      resetButton.onAction = handle {
        model.onReset()
      }
    
      private def format2d(t: Number) = f"${t.longValue()}%02d"
    }

    The ModelFX implements the logic for the operation of the Stop Watch. Notice that there are no direct references to UI controls. The connection to the UI is through the properties (like minutes). The ModelFX is not aware how the ControllerFX is implemented. (org.scalafx.extras.mvcfx.stopwatch.StopWatchModel)

    package org.scalafx.extras.mvcfx.stopwatch
    
    import javafx.{concurrent => jfxc}
    
    import org.scalafx.extras._
    import org.scalafx.extras.mvcfx.ModelFX
    
    import scalafx.Includes._
    import scalafx.beans.property.{LongProperty, ReadOnlyBooleanProperty, ReadOnlyBooleanWrapper}
    
    class StopWatchModel extends ModelFX {
    
      private val _running = ReadOnlyBooleanWrapper(false)
    
      val running: ReadOnlyBooleanProperty = _running.readOnlyProperty
    
      private val counterService = new CounterService()
      counterService.period = 10.ms
    
      val minutes = new LongProperty()
      val seconds = new LongProperty()
      val secondFraction = new LongProperty()
    
      counterService.elapsedTime.onChange { (_, _, newValue) =>
        val t = newValue.longValue()
        secondFraction.value = t % 1000
        seconds.value = (t / 1000) % 60
        minutes.value = t / 1000 / 60
      }
    
      def onStart(): Unit = {
        counterService.doResume()
        _running.value = true
      }
    
      def onStop(): Unit = {
        counterService.doPause()
        _running.value = false
      }
    
      def onReset(): Unit = counterService.doReset()
    
      private class CounterService extends jfxc.ScheduledService[Long] {
    
        private var timeAccumulator: Long = 0
        private var restartTime: Long = 0
    
        val elapsedTime = new LongProperty()
    
        override def createTask(): jfxc.Task[Long] = {
          new jfxc.Task[Long]() {
            override protected def call(): Long = {
              val ct = System.currentTimeMillis()
              val et = timeAccumulator + (ct - restartTime)
              onFX {elapsedTime.value = et}
              et
            }
          }
        }
    
        def doPause(): Unit = {
          val ct = System.currentTimeMillis()
          timeAccumulator += (ct - restartTime)
          onFX {elapsedTime.value = timeAccumulator}
          this.cancel()
        }
    
        def doResume(): Unit = {
          restartTime = System.currentTimeMillis()
          this.restart()
        }
    
        def doReset(): Unit = {
          timeAccumulator = 0
          onFX {elapsedTime.value = 0}
        }
      }
    }

    The MVCfx implementation is very simple, it only needs instance of the model and information about location of the FXML resource. (org.scalafx.extras.mvcfx.stopwatch.StopWatch)

    package org.scalafx.extras.mvcfx.stopwatch
    
    import org.scalafx.extras.mvcfx.MVCfx
    
    class StopWatch(val model: StopWatchModel = new StopWatchModel())
      extends MVCfx("/org/scalafx/extras/mvcfx/stopwatch/StopWatchView.fxml")

    The MVCfx can be easily used in an Application class to create UI. (org.scalafx.extras.mvcfx.stopwatch.StopWatchApp)

    package org.scalafx.extras.mvcfx.stopwatch
    
    import scala.language.implicitConversions
    import scalafx.application.JFXApp3
    import scalafx.application.JFXApp3.PrimaryStage
    import scalafx.scene.Scene
    import scalafx.scene.layout.BorderPane
    
    object StopWatchApp extends JFXApp3 {
      override def start(): Unit = {
        stage = new PrimaryStage {
          scene = new Scene {
            title = "StopWatch"
            root = new BorderPane {
              center = new StopWatch().view
            }
          }
        }
      }
    }
    Definition Classes
    extras
  • package pong
    Definition Classes
    extras
p

org.scalafx.extras

generic_pane

package generic_pane

Content Hierarchy
Ordering
  1. Alphabetic
Visibility
  1. Public
  2. Protected

Type Members

  1. class DefaultLastDirectoryHandler extends LastDirectoryHandler

    Default implementation of the LastDirectoryHandler.

  2. class DirectorySelectionField extends AnyRef

    Directory selection control, accessible through view.

    Directory selection control, accessible through view. The text field shows the path, the button opens a dialog to select the directory.

  3. class FileSelectionField extends AnyRef

    File selection control, accessible through view.

    File selection control, accessible through view. The text field shows the path, the button allow browsing to select the File.

  4. class GenericDialogFX extends GenericPaneBase

    A helper for crating custom dialogs.

    A helper for crating custom dialogs. Particularly suited for creation of input dialogs.

    There are 3 steps to using a dialog: 1. Creation, where elements of the dialog are appended vertically using add*(...) methods, for instance, addStringField(label, defaultText) 2. User interaction, dialog is displayed using showDialog() method 3. Reading of input, once the dialog is closed, dialog content can be read using next*() methods. Content is read in the order it is added.

    Here is en example:

    val dialog =
      new GenericDialogFX(
        title = "GenericDialogFX Demo",
        "Fancy description can go here."
      ) {
        addCheckbox("Check me out!", defaultValue = false)
        addCheckbox("Check me too!", defaultValue = true)
      }
    
    dialog.showDialog()
    
    if (dialog.wasOKed) {
      val select1 = dialog.nextBoolean()
      val select2 = dialog.nextBoolean()
    
      println(s"Selection 1: $select1")
      println(s"Selection 2: $select2")
    }
    See also

    GenericPane

  5. class GenericPane extends GenericPaneBase

    A helper for crating custom panes.

    A helper for crating custom panes. Particularly suited for creation of input controls.

    There are 4 steps to using a generic pane:

    1. Creation, where elements of the pane are appended vertically using add*(...) methods, * for instance, addStringField(label, defaultText)

    2. Adding the pane to the UI

    3. User interaction, after the pane is displayed

    4. Optionally, reading of input. Pane editable content can be read using next*() methods. Content is read in the order it is added. The whole pane content can be read multiple tiles. Remember to call resetReadout() to ensure that reading is restarted from the beginning of the pane.

    Example:

    // Build a pane
    val gp = new GenericPane()
    gp.addDirectoryField("Input", "images")
    gp.addDirectoryField("Output", "output")
    
    // Use it in some other control
    ...
    
    // Later ...
    // Print its content
    gp.resetReadout()
    println(s"Input dir : ${gp.nextString()}")
    println(s"Output dir: ${gp.nextString()}")
    See also

    GenericDialogFX

  6. trait GenericPaneBase extends AnyRef
  7. trait LastDirectoryHandler extends AnyRef

    Customize how directory selections are remembered between uses of the dialog.

  8. class NumberTextField extends TextField

Value Members

  1. object DirectorySelectionField
  2. object GenericDialogFX
  3. object Utils

Ungrouped