{"id":15175222,"url":"https://github.com/scalafx/scalafx-extras","last_synced_at":"2025-06-28T22:42:47.651Z","repository":{"id":43902204,"uuid":"77012968","full_name":"scalafx/scalafx-extras","owner":"scalafx","description":"Additions to ScalaFX that do not have corresponding concepts in JavaFX","archived":false,"fork":false,"pushed_at":"2025-04-25T18:20:26.000Z","size":13755,"stargazers_count":12,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-25T19:23:50.537Z","etag":null,"topics":["javafx","scala","scalafx","scalafx-extras","scalafx-framework"],"latest_commit_sha":null,"homepage":null,"language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/scalafx.png","metadata":{"files":{"readme":"ReadMe.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2016-12-21T03:36:23.000Z","updated_at":"2025-04-25T18:20:29.000Z","dependencies_parsed_at":"2024-09-18T03:01:17.823Z","dependency_job_id":"e73b2b13-97d6-4fd7-8dcb-2fa3cc63bfaa","html_url":"https://github.com/scalafx/scalafx-extras","commit_stats":{"total_commits":233,"total_committers":1,"mean_commits":233.0,"dds":0.0,"last_synced_commit":"6179ff7642dadf26963bef3d86a11c070da56a4c"},"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"purl":"pkg:github/scalafx/scalafx-extras","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scalafx%2Fscalafx-extras","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scalafx%2Fscalafx-extras/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scalafx%2Fscalafx-extras/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scalafx%2Fscalafx-extras/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/scalafx","download_url":"https://codeload.github.com/scalafx/scalafx-extras/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scalafx%2Fscalafx-extras/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262508266,"owners_count":23321978,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["javafx","scala","scalafx","scalafx-extras","scalafx-framework"],"created_at":"2024-09-27T12:04:52.761Z","updated_at":"2025-06-28T22:42:47.643Z","avatar_url":"https://github.com/scalafx.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"ScalaFX Extras\n==============\n\n[![Scala CI](https://github.com/scalafx/scalafx-extras/actions/workflows/scala.yml/badge.svg)](https://github.com/scalafx/scalafx-extras/actions/workflows/scala.yml)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.scalafx/scalafx-extras_3/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.scalafx/scalafx-extras_3)\n[![Scaladoc](https://javadoc.io/badge2/org.scalafx/scalafx-extras_3/scaladoc.svg)](https://javadoc.io/doc/org.scalafx/scalafx-extras_3)\n\nScalaFX Extras are additions to ScalaFX that simplify creation of User interfaces. In contrast to ScalaFX core, the\nExtras do not have direct corresponding concepts in JavaFX.\n\n**Contents**\n\n\u003c!-- TOC --\u003e\n\n* [Project Structure](#project-structure)\n* [SBT](#sbt)\n* [Features](#features)\n    * [Helper Methods](#helper-methods)\n    * [Simpler Display of Standard Dialogs](#simpler-display-of-standard-dialogs)\n    * [Easy Custom Panes](#easy-custom-panes)\n    * [Easy Custom Dialogs](#easy-custom-dialogs)\n    * [Edit a Case Class object with AutoDialog](#edit-a-case-class-object-with-autodialog)\n    * [BusyWorker](#busyworker)\n        * [Example 1](#example-1)\n        * [Example 2](#example-2)\n    * [Simpler Use of FXML with MVCfx Pattern](#simpler-use-of-fxml-with-mvcfx-pattern)\n    * [ImageDisplay Component](#imagedisplay-component)\n    * [Batch Processing and Progress Dialog](#batch-processing-and-progress-dialog)\n* [Demos](#demos)\n    * [StopWatch Application](#stopwatch-application)\n    * [ShowMessage Demo](#showmessage-demo)\n    * [BusyWorker Demo](#busyworker-demo)\n    * [ImageDisplay Demo](#imagedisplay-demo)\n* [Status](#status)\n* [Discussion and Support](#discussion-and-support)\n* [License](#license)\n\n\u003c!-- TOC --\u003e\n\nProject Structure\n-----------------\n\nModule `scalafx-extras` contain feature implementations. Module `scalafx-extras-demos` illustrates use\nof `scalafx-extras`\n\nSBT\n---\n\nTo use ScalaFX Extras with SBT add following dependency:\n\n```\nlibraryDependencies += \"org.scalafx\" %% \"scalafx-extras\" % scalafx_extras_version\n```\n\nThe latest published ScalaFX Extras\nversion: [![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.scalafx/scalafx-extras_2.12/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.scalafx/scalafx-extras_2.12)\n\nFeatures\n--------\n\n### Helper Methods\n\nPackage `org.scalafx.extras` contains basic helper methods for running tasks on threads and showing exception messages.\nThe main helper methods:\n\n* `onFX` run code on FX Application thread in parallel\n* `onFXAndWait` run code on FX Application thread and wait till finished\n* `offFX` run code a thread in parallel\n* `offFXAndWait` run code a thread and wait till finished\n\nExample scheduling some code on FX Application thread\n\n```scala\nonFX {\n  counterService.doResume()\n  _running.value = true\n}\n\n```\n\nExample execution some code on a separate thread and waiting for the result of computation\n\n```scala\nval x = offFXAndWait {\n  val a = 3\n  val b = 7\n  a * b\n}\n\n```\n\n### Simpler Display of Standard Dialogs\n\nStandard dialogs can be quickly displayed using functions provided my `ShowMessage`. For instance,\n\n```scala\nimport org.scalafx.extras.ShowMessage\n\nShowMessage.information(\n  \"Dialog Title\",\n  \"This is the information 'header'\",\n  \"This is the information detailed 'content'.\",\n  parentWindow\n)\n```\n\nDialog types supported:\n\n* `confirmation`\n* `confirmationYesNoCancel`\n* `error`\n* `exception`\n* `information`\n* `warning`\n\n`ShowMessage` can be also used as a mixin to be used within a class where there is the same `parentWindow`.\nIt is typically used with a UI `Model`. The dialogs can be\ndisplayed using a single method, like `showInformation`, `showConfirmation`. `ShowMessage` takes care of blocking parent\nwindows and using parent icons in dialogs. It can also log warnings, errors, and exceptions when warnings, errors, and\nexceptions dialogs are displayed.\n\n```scala\nclass MyUIModel extends Model with ShowMessage {\n\n  def onSomeUserAction(): Unit = {\n    // ...\n    showInformation(\"Dialog Title\",\n      \"This is the information 'header'\",\n      \"This is the information detailed 'content'.\")\n    // ...\n  }\n\n  // ...\n}\n```  \n\nThe demos module has a complete example of a simple application in `ShowMessageDemoApp`.\n\n### Easy Custom Panes\n\n`GenericPane` is a helper class that simplifies creation of panes. Particularly suited for creation of input controls.\n\nTypically there are 4 steps to using a `GenericPane`:\n\n1. Creation, where elements of the pane are appended vertically using `add*(...)` methods, for instance,\n   `addStringField(label, defaultText)`\n\n2. Adding the pane to the UI\n\n3. User interaction, after the pane is displayed\n\n4. Optionally, reading of input. Pane's editable content can be read using `next*()` methods. Content is read in the\n   order it is added. The whole pane content can be read multiple tiles. Remember to call `resetReadout()` to ensure\n   that reading is restarted from the beginning of the pane.\n\nA complete example in Scala 3. Shows a pane with 2 directory selection fields and a button \"Print Fields\". When the\nbutton is pressed values\nof the directory fields are printed\n\n```scala 3\nimport org.scalafx.extras.generic_pane.GenericPane\nimport scalafx.application.JFXApp3\nimport scalafx.application.JFXApp3.PrimaryStage\nimport scalafx.geometry.Insets\nimport scalafx.scene.Scene\nimport scalafx.scene.control.Button\nimport scalafx.scene.layout.VBox\n\nobject GenericPaneDemo extends JFXApp3:\n\n  override def start(): Unit =\n\n    val gp = new GenericPane():\n      addDirectoryField(\"Input\", \"images\")\n      addDirectoryField(\"Output\", \"output\")\n\n    stage = new PrimaryStage:\n      title = \"GenericPane Demo\"\n      scene = new Scene:\n        content = new VBox:\n          padding = Insets(7, 7, 7, 7)\n          spacing = 7\n          children = Seq(\n            gp.pane,\n            new Button(\"Print Fields\"):\n              onAction = (_) =\u003e\n                gp.resetReadout()\n                println(s\"Input dir : ${gp.nextString()}\")\n                println(s\"Output dir: ${gp.nextString()}\")\n          )\n```\n\n![GenericPane Demo](notes/assets/GenericPane.png)\n\n### Easy Custom Dialogs\n\nCustom dialogs can be quickly created using `GenericDialogFX` class. This class is particularly suited for creation of\ninput dialogs.\n\nThere are 3 steps to using the `GenericDialogFX`:\n\n1. Creation, where elements of the dialog are appended vertically using `add*(...)` methods, for\n   instance,`addStringField(label, defaultText)`\n2. User interaction, dialog is displayed using `showDialog()` method\n3. Reading of input, once the dialog is closed, dialog content can be read using `next*()` methods. Content is read in\n   the order it is added.\n\nHere is en example:\n\n```scala\n// Create a dialog\nval dialog =\n  new GenericDialogFX(\n    title = \"GenericDialogFX Demo\",\n    header = \"Fancy description can go here.\"\n  ) {\n    // Add fields\n    addCheckbox(\"Check me out!\", defaultValue = false)\n    addCheckbox(\"Check me too!\", defaultValue = true)\n  }\n\n// Show dialog to the user\ndialog.showDialog()\n\n// Read input provided by the user\nif (dialog.wasOKed) {\n  val select1 = dialog.nextBoolean()\n  val select2 = dialog.nextBoolean()\n\n  println(s\"Selection 1: $select1\")\n  println(s\"Selection 2: $select2\")\n} else {\n  println(\"Dialog was cancelled.\")\n}\n```\n\n![GenericDialogFX Demo](notes/assets/GenericDialogFX_2.png)\n\nA more elaborate example is in the `GenericDialogFXDemo`.\n\n### Edit a Case Class object with AutoDialog\n\n`AutoDialog` can be used too quickly open auto generated dialog from case class. After closing, the dialog will return\nan edited version of the input case class.\n\nHere is an example of usage:\n\n```scala\nimport org.scalafx.extras.auto_dialog.AutoDialog\n\ncase class FilterOptions(kernelSize: Int = 7,\n                         start: Double = 3.14,\n                         tag: String = \"alpha\",\n                         debugMode: Boolean = false)\n\nval filterOptions = FilterOptions()\n\nval result: Option[FilterOptions] =\n  new AutoDialog(filterOptions)\n    .showDialog(\n      \"AutoDialog Demo\",\n      \"Fields are auto generated from `FilterOptions` object\")\n\nprintln(s\"Result: $result\")\n```\n\n![GenericDialogFX Demo](notes/assets/AutoDialog.png)\n\n### BusyWorker\n\nBusyWorker helps to run a UI task on separate threads (other than the JavaFX Application thread). It will show busy\ncursor and disable specified nodes while the task is performed. It gives an option to show progress and status messages.\n`BusyWorker` takes care of handling exceptions and displaying error dialogs. It provides for an option to perform custom\nfinish actions after the task is completed.\n\n#### Example 1\n\nBelow is a simple example of using `BusyWorker`. When the task is running, `BusyWorker` will disable the root pane of\nthe `parentWindow` to indicate that a task is performed. It will also change the cursor in the root pane to \"busy\". When\ntask is done, the cursor will be changed back to default and root pane will be enabled back.\n\n```scala\nnew BusyWorker(\"Simple Task\", parentWindow).doTask { () =\u003e\n  Thread.sleep(1000)\n  print(1 + 1)\n}\n```\n\n#### Example 2\n\nHere is a little more elaborated example. It updates a progress message and progress indicator.\n\n```scala\nval buttonPane: Pane = ???\nval progressLabel: Label = ???\nval progressBar: ProgressBar = ???\n\nval busyWorker = new BusyWorker(\"BusyWorker Demo\", buttonPane) {\n  progressLabel.text \u003c== progressMessage\n  progressBar.progress \u003c== progressValue\n}\n\nval button = new Button(\"Click Me\") {\n  onAction = () =\u003e busyWorker.doTask(\"Task 1\")(\n    new SimpleTask[String] {\n      override def call(): String = {\n        val maxItems = 10\n        for (i \u003c- 1 to maxItems) {\n          println(i)\n          message() = s\"Processing item $i/$maxItems\"\n          progress() = (i - 1) / 10.0\n          Thread.sleep(250)\n        }\n        progress() = 1\n        \"Done\"\n      }\n    }\n  )\n}\n```\n\nThe full code example can be found in the\n[BusyWorkerDemo][BusyWorkerDemo].\n\n### Simpler Use of FXML with MVCfx Pattern\n\nPackage `org.scalafx.extras.mvcfx` contains classes for creating with UI components based on FXML that use\nModel-View-Controller, here we call it the MVCfx Pattern. See the wiki page [MVCfx Pattern] for details.\n\nThe demos module has a complete example of a simple application: [StopWatchApp][StopWatchDemo].\n\n### ImageDisplay Component\n\nImageDisplay Component is an image view with the ability to zoom in, zoom out, zoom to fit.\nIt can also automatically resize to parent size (zoom-to-fit).\nImage cane also rotated and flipped along the X and Y axis.\n\nImageDisplay provides an option to show overlay on top of the image. Overlays scale and rotate with the image.\n\n### Batch Processing and Progress Dialog\n\nWork in progress\n\n* Helper UI for running batch processing tasks, see `BatchRunnerProgressDemoApp` for example of use\n* Component for display of the progress of batch processing tasks, see `ProgressStatusDemoApp` for example of use\n\nDemos\n-----\n\nModule [scalafx-extras-demos][scalafx-extras-demos] contains examples of using ScalaFX Extras.\n\n### StopWatch Application\n\n[StopWatchApp][StopWatchDemo] is an application that illustrates uses of the [MVCfx Pattern]: a Model-View-Controller\nwith FXML layout.\n\n![StopWatch Demo](notes/assets/StopWatchDemo.gif)\n\nThere are slight differences between Scala 2 and 3 related to use of annotations. See [StopWatchDemo Scala 2]\nand [StopWatchDemo Scala 3] files for details. It is described in details in [MVCfx Pattern] wiki page.\n\n### ShowMessage Demo\n\n[ShowMessageDemoApp][ShowMessageDemo] is a full example of using `ShowMessage` and MVCfx.\n\n![ShowMessage Demo](notes/assets/ShowMessageDemo.gif)\n\nThere are slight differences between Scala 2 and 3 related to use of annotations. See [ShowMessageDemo Scala 2]\nand [ShowMessageDemo Scala 3] files for details.\n\n### BusyWorker Demo\n\n[BusyWorkerDemo][BusyWorkerDemo] illustrated different aspects of using `BusyWorker`.\n\n![BusyWorker Demo](notes/assets/BusyWorkerDemo.gif)\n\n### ImageDisplay Demo\n\n[ImageDisplayDemoApp][ImageDisplayDemo] a simple example of an application that can display images,\nwith the ability to zoom in, zoom out, and fit to the current window, flip, and rotate the image.\nIllustrates use of the `ImageDisplay` component.\n\n![Image Display Demo](notes/assets/ImageDisplayDemo.gif)\n\n### BatchRunnerWithProgress Demo\n\n[BatchRunnerWithProgressDemoApp] demo of `BatchRunnerWithProgress` GUI.\n\n![BatchRunnerWithProgress Demo](notes/assets/BatchRunnerProgressDemoApp.gif)\n\n\nStatus\n------\n\nScalaFX Extras is still quite experimental and APIs may change significantly.\n\nDiscussion and Support\n----------------------\n\nFor discussion and support, please use [ScalaFX Users Group]\nor project [Discussions]. Please report issues using the projects Issue tracker.\n\n\nLicense\n-------\n\nBSD-3-Clause ScalaFX license.\n\n[scalafx-extras-demos]: scalafx-extras-demos\n\n[MVCfx Pattern]: https://github.com/scalafx/scalafx-extras/wiki/MVCfx-Pattern\n\n[BusyWorkerDemo]: scalafx-extras-demos/src/main/scala/org/scalafx/extras/BusyWorkerDemo.scala\n\n[ImageDisplayDemo]: scalafx-extras-demos/src/main/scala/org/scalafx/extras/image/ImageDisplayDemoApp.scala\n\n[ShowMessageDemo]: scalafx-extras-demos/src/main/scala/org/scalafx/extras/showmessage\n\n[ShowMessageDemo Scala 2]: scalafx-extras-demos/src/main/scala-2/org/scalafx/extras/showmessage\n\n[ShowMessageDemo Scala 3]: scalafx-extras-demos/src/main/scala-3/org/scalafx/extras/showmessage\n\n[StopWatchDemo]: scalafx-extras-demos/src/main/scala/org/scalafx/extras/mvcfx/stopwatch\n\n[StopWatchDemo Scala 2]: scalafx-extras-demos/src/main/scala-2/org/scalafx/extras/mvcfx/stopwatch\n\n[StopWatchDemo Scala 3]: scalafx-extras-demos/src/main/scala-3/org/scalafx/extras/mvcfx/stopwatch\n\n[BatchRunnerWithProgressDemoApp]: scalafx-extras-demos/src/main/scala-3/org/scalafx/extras/batch/BatchRunnerWithProgressDemoApp.scala\n\n[ScalaFX Users Group]: https://groups.google.com/forum/#!forum/scalafx-users\n\n[Discussions]: https://github.com/scalafx/scalafx-extras/discussions","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscalafx%2Fscalafx-extras","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fscalafx%2Fscalafx-extras","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscalafx%2Fscalafx-extras/lists"}