I am using scalas to run a simple scala.swing application:
#!/usr/bin/env scalas
/***
scalaVersion := "2.12.6"
libraryDependencies += "org.scala-lang.modules" %% "scala-swing" % "2.1.1"
*/
import scala.swing._
object FirstSwingApp extends SimpleSwingApplication {
def top = new MainFrame {
title = "First Swing App"
contents = new Button {
text = "Click me"
}
}
}
This compiles and runs (on OSX 10.14), but there is no visible output; the process just terminates after a few seconds. What have I done wrong?
Judging from this documentation https://www.scala-sbt.org/release/docs/Scripts.html - scalas doesn't work like java -jar ..., that is, it isn't running your main class in some object.
It merely executes code as if it was REPL, so if you want to execute code, run it yourself:
#!/usr/bin/env scalas
/***
scalaVersion := "2.12.6"
libraryDependencies += "org.scala-lang.modules" %% "scala-swing" % "2.1.1"
*/
import scala.swing._
// creates object but doesn't run anything
object FirstSwingApp extends SimpleSwingApplication {
def top = new MainFrame {
title = "First Swing App"
contents = new Button {
text = "Click me"
}
}
}
FirstSwingApp.main(new Array[String](0)) // run main manually, or whatever you prefer
Related
I use the sbt-release plugin for a couple of projects. One step I use is docker:publish for sbt-native-packager to push an image to Docker hub.
sbt-native-packager relies on the dockerUpdateLatest setting to decide whether to update the latest tag. The default is false, and if it is true it will update latest.
For one project, that has no sub projects under root, I am able to use a custom ReleaseStep to change that setting depending on if I am releasing a SNAPSHOT, i.e. I do not want to update the latest tag if the version ends in SNAPSHOT.
lazy val setDockerReleaseSettings = ReleaseStep(action = oldState => {
// dockerUpdateLatest is set to true if the version is not a SNAPSHOT
val extracted = Project.extract(oldState)
val v = extracted.get(Keys.version)
val snap = v.endsWith("SNAPSHOT")
if (!snap) extracted
.appendWithSession(Seq(dockerUpdateLatest := true), oldState)
else oldState
})
The above works for that project.
For the other project, there are multiple projects aggregated under root. I would like to do something like
lazy val setDockerReleaseSettings = ReleaseStep(action = oldState => {
// dockerUpdateLatest is set to true if the version is not a SNAPSHOT
val extracted = Project.extract(oldState)
val v = extracted.get(Keys.version)
val snap = v.endsWith("SNAPSHOT")
if (!snap) extracted
.appendWithSession(Seq(dockerUpdateLatest in api := true, dockerUpdateLatest in portal := true), oldState)
else oldState
})
But it does not seem to work. I also tried dockerUpdateLatest in Global, and dockerUpdateLatest in root to no avail. Any ideas how to alter dockerUpdateLatest in these sub projects?
Was able to solve it with set every dockerUpdateLatest := true. I made a custom ReleaseStep like so
lazy val createSetDockerUpdateLatestCommand = ReleaseStep(action = state => {
// dockerUpdateLatest is set to true if the version is not a SNAPSHOT
val snap = Project.extract(state).get(Keys.version).endsWith("SNAPSHOT")
val setDockerUpdateLatest = if (!snap)
Command.command("setDockerUpdateLatest") {
"set every dockerUpdateLatest := true" ::
_
}
else
Command.command("setDockerUpdateLatest") {
"" ::
_
}
state.copy(definedCommands = state.definedCommands :+ setDockerUpdateLatest)
})
Then I run setDockerUpdateLatest
In an implementation of an FSM (old story: modeling an Elevator/Lift), I am trying to see if I can test whether the FSM follows a transition from and to the same State. It seems, it is not happening, but that surprises me because according to this discussion on StackOverFlow, the fix is available in Akka 2.4.x.
Here's the relevant portion of the code:
class LiftCarriageWithMovingState extends Actor
with FSM[LiftState,LiftData]
with ActorLogging
{
import context._
val mxTimeToWaitStopping = 500 milliseconds
private var pendingPassengerRequests: Vector[NextStop] = Vector.empty
private var currentFloorID = 0 // Always start at Ground Floor
val timeToReachNextFloor = 1000 millis // up or down, same time taken
private val dontCare: StateFunction = { /* ... */ }
private val powerYourselfOff: StateFunction = { /* ... */ }
private val powerYourselfOn: StateFunction = { /* ... */ }
private val beReady: StateFunction = { /* ... */ }
private val moveToWaitingPassenger: StateFunction = { /* ... */ }
private val transportPassengerToDest: StateFunction = {/* ... */ }
private val actWhenStoppedForLongEnough: StateFunction = {
case Event(StateTimeout,_) =>
if (this.pendingPassengerRequests isEmpty) {
println("timeout in Stopped, no passenger requests pending")
goto (Stopped)
}
else {
println("timeout in Stopped, moving to floor(" + this.pendingPassengerRequests.head + ")")
simulateMovementTo(this.pendingPassengerRequests.head)
goto(Moving)
}
}
startWith(PoweredOff,InitialData)
when (PoweredOff) (powerYourselfOn orElse
dontCare)
when (PoweredOn) (powerYourselfOff orElse
beReady orElse
dontCare)
when (Ready) (moveToWaitingPassenger orElse
transportPassengerToDest )
when (Stopped) (actWhenStoppedForLongEnough orElse
moveToWaitingPassenger orElse
transportPassengerToDest )
when (Moving) {
case Event(ReachedFloor(floorID, PurposeOfMovement.ToWelcomeInAnWaitingPassenger),_) =>
currentFloorID = pendingPassengerRequests.head.floorID
pendingPassengerRequests = pendingPassengerRequests.tail
goto (Stopped) forMax(this.mxTimeToWaitStopping)
case Event(ReachedFloor(floorID,PurposeOfMovement.ToAllowATransportedPassengerAlight),_) =>
currentFloorID = pendingPassengerRequests.head.floorID
pendingPassengerRequests = pendingPassengerRequests.tail
goto (Stopped) forMax(this.mxTimeToWaitStopping)
// .... Other events
}
whenUnhandled {
// Event handlers...
}
onTransition {
case Stopped -> Stopped => {
println("Remaining in Stopped ...")
}
}
// Rest of the Actor
I have pruned unnecessary parts, because the main point is this:
When the actor receives a
Event(ReachedFloor(floorID, PurposeOfMovement.ToWelcomeInAnWaitingPassenger),_)
when it is in the Moving state, it switches to Stopping state, with a specified timeout. When that timer fires while the FSM is Stopped, the handler that is supposed to execute, is named (shown above too):
actWhenStoppedForLongEnough
Here, I am checking a certain exit condition, and if I am not happy, I am switching back to same Stopped state again. I am using goto() now, but the original code had stay().
I have set up a onTransition block too (shown above again), to prove that the transition indeed does happen.
onTransition {
case Stopped -> Stopped => {
println("Remaining in Stopped ...")
}
}
When I run the code, the println statement is not executed, at all.
I also have a testcode; the relevant testcase is this:
var carriage: ActorRef = _
override def beforeAll(): Unit = {
super.beforeAll()
carriage = TestActorRef(Props(new LiftCarriageWithMovingState))
carriage ! SubscribeTransitionCallBack(testActor)
}
"A LiftCarriage" must {
"be ready, when it settles down after being PoweredOn" in {
expectMsg(Duration(100, TimeUnit.MILLISECONDS), new CurrentState(carriage,PoweredOff))
carriage ! InstructedToPowerOn
expectMsg (new Transition(carriage,PoweredOff,PoweredOn))
carriage ! BeReady
expectMsg((new Transition(carriage,PoweredOn,Ready)))
}
"move to where a passenger is waiting, if ready" in {
carriage ! ReportCurrentFloor
expectMsg(StoppedAt(0))
carriage ! PassengerIsWaitingAt(3)
expectMsg(new Transition(carriage,Ready,Moving))
expectMsg(Duration(5000, TimeUnit.MILLISECONDS), new Transition(carriage,Moving, Stopped))
carriage ! ReportCurrentFloor
expectMsg(StoppedAt(3))
}
"let a passenger in and transport her to her destination" in {
carriage ! ReportCurrentFloor
expectMsg(StoppedAt(3))
carriage ! PassengerRequestsATransportTo(Vector(7))
expectMsg(new Transition(carriage,Stopped,Moving))
expectMsg(Duration(5000, TimeUnit.MILLISECONDS), new Transition(carriage,Moving,Stopped))
carriage ! ReportCurrentFloor
expectMsg(StoppedAt(7))
// This always times out and fails.
expectMsg(Duration(5000, TimeUnit.MILLISECONDS), new Transition(carriage,Stopped,Stopped))
}
I am trying to think hard as to if and where the gap in my understanding lies, but failing. Any hints?
Here's the build.sbt:
name := """akka-sample-fsm-scala"""
version := "2.4"
scalaVersion := "2.11.8"
libraryDependencies ++= Seq(
// https://mvnrepository.com/artifact/com.typesafe.akka/akka-actor_2.11
"com.typesafe.akka" % "akka-actor_2.11" % "2.4.12",
// https://mvnrepository.com/artifact/org.scalatest/scalatest_2.11
"org.scalatest" % "scalatest_2.11" % "2.1.3",
// https://mvnrepository.com/artifact/com.typesafe.akka/akka-testkit_2.11,
"com.typesafe.akka" % "akka-testkit_2.11" % "2.3.15"
)
Another question - which is quite similar to mine - has been asked earlier, but I don't see any responses. May be, the answer has been found already but not yet shared.
I am trying to find a way to use drag and drop in my matlab GUI. The closest I've found is this.
However, I would like the result to look like this:
When a file has been dropped, all I need is the path of the file and a call to my load function.
All suggestions are much appreciated!
This submission by Maarten van der Seijs on the file exchange seems to solve it.
It creates a callback function which can be coupled to java swing GUI components, as shown in the attached demo.
It uses a java class, which is a thin wrapper around java.awt.dnd.DropTarget:
import java.awt.dnd.*;
import java.awt.datatransfer.*;
import java.util.*;
import java.io.File;
import java.io.IOException;
public class MLDropTarget extends DropTarget
{
/**
* Modified DropTarget to be used for drag & drop in MATLAB UI control.
*/
private static final long serialVersionUID = 1L;
private int droptype;
private Transferable t;
private String[] transferData;
public static final int DROPERROR = 0;
public static final int DROPTEXTTYPE = 1;
public static final int DROPFILETYPE = 2;
#SuppressWarnings("unchecked")
#Override
public synchronized void drop(DropTargetDropEvent evt) {
// Make sure drop is accepted
evt.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
// Set droptype to zero
droptype = DROPERROR;
// Get transferable and analyze
t = evt.getTransferable();
try {
if (t.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
// Interpret as list of files
List<File> fileList = (ArrayList<File>) t.getTransferData(DataFlavor.javaFileListFlavor);
transferData = new String[fileList.size()];
for (int i = 0; i < fileList.size(); i++)
transferData[i] = fileList.get(i).getAbsolutePath();
droptype = DROPFILETYPE;
}
else if (t.isDataFlavorSupported(DataFlavor.stringFlavor)) {
// Interpret as string
transferData[0] = (String) t.getTransferData(DataFlavor.stringFlavor);
droptype = DROPTEXTTYPE;
}
} catch (UnsupportedFlavorException e) {
droptype = DROPERROR;
super.drop(evt);
return;
} catch (IOException e) {
droptype = DROPERROR;
super.drop(evt);
return;
}
// Call built-in drop method (fire MATLAB Callback)
super.drop(evt);
}
public int getDropType() {
return droptype;
}
public Transferable getTransferable() {
return t;
}
public String[] getTransferData() {
return transferData;
}
}
which is then initialized and called by a MATLAB class:
classdef (CaseInsensitiveProperties) dndcontrol < handle
%DNDCONTROL Class for Drag & Drop functionality.
% obj = DNDCONTROL(javaobj) creates a dndcontrol object for the specified
% Java object, such as 'javax.swing.JTextArea' or 'javax.swing.JList'. Two
% callback functions are available: obj.DropFileFcn and obj.DropStringFcn,
% that listen to drop actions of respectively system files or plain text.
%
% The Drag & Drop control class relies on a Java class that need to be
% visible on the Java classpath. To initialize, call the static method
% dndcontrol.initJava(). The Java class can be adjusted and recompiled if
% desired.
%
% DNDCONTROL Properties:
% Parent - The associated Java object.
% DropFileFcn - Callback function for system files.
% DropStringFcn - Callback function for plain text.
%
% DNDCONTROL Methods:
% dndcontrol - Constructs the DNDCONTROL object.
%
% DNDCONTROL Static Methods:
% defaultDropFcn - Default callback function for drop events.
% demo - Runs the demonstration script.
% initJava - Initializes the Java class.
% isInitialized - Checks if the Java class is visible.
%
% A demonstration is available from the static method dndcontrol.demo().
%
% Example:
% dndcontrol.initJava();
% dndcontrol.demo();
%
% See also:
% uicontrol, javaObjectEDT.
%
% Written by: Maarten van der Seijs, 2015.
% Version: 1.0, 13 October 2015.
properties (Hidden)
dropTarget;
end
properties (Dependent)
%PARENT The associated Java object.
Parent;
end
properties
%DROPFILEFCN Callback function executed upon dropping of system files.
DropFileFcn;
%DROPSTRINGFCN Callback function executed upon dropping of plain text.
DropStringFcn;
end
methods (Static)
function initJava()
%INITJAVA Initializes the required Java class.
%Add java folder to javaclasspath if necessary
if ~dndcontrol.isInitialized();
classpath = fileparts(mfilename('fullpath'));
javaclasspath(classpath);
end
end
function TF = isInitialized()
%ISINITIALIZED Returns true if the Java class is initialized.
TF = (exist('MLDropTarget','class') == 8);
end
end
methods
function obj = dndcontrol(Parent,DropFileFcn,DropStringFcn)
%DNDCONTROL Drag & Drop control constructor.
% obj = DNDCONTROL(javaobj) contstructs a DNDCONTROL object for
% the given parent control javaobj. The parent control should be a
% subclass of java.awt.Component, such as most Java Swing widgets.
%
% obj = DNDCONTROL(javaobj,DropFileFcn,DropStringFcn) sets the
% callback functions for dropping of files and text.
% Check for Java class
assert(dndcontrol.isInitialized(),'Javaclass MLDropTarget not found. Call dndcontrol.initJava() for initialization.')
% Construct DropTarget
obj.dropTarget = handle(javaObjectEDT('MLDropTarget'),'CallbackProperties');
set(obj.dropTarget,'DropCallback',{#dndcontrol.DndCallback,obj});
set(obj.dropTarget,'DragEnterCallback',{#dndcontrol.DndCallback,obj});
% Set DropTarget to Parent
if nargin >=1, Parent.setDropTarget(obj.dropTarget); end
% Set callback functions
if nargin >=2, obj.DropFileFcn = DropFileFcn; end
if nargin >=3, obj.DropStringFcn = DropStringFcn; end
end
function set.Parent(obj, Parent)
if isempty(Parent)
obj.dropTarget.setComponent([]);
return
end
if isa(Parent,'handle') && ismethod(Parent,'java')
Parent = Parent.java;
end
assert(isa(Parent,'java.awt.Component'),'Parent is not a subclass of java.awt.Component.')
assert(ismethod(Parent,'setDropTarget'),'DropTarget cannot be set on this object.')
obj.dropTarget.setComponent(Parent);
end
function Parent = get.Parent(obj)
Parent = obj.dropTarget.getComponent();
end
end
methods (Static, Hidden = true)
%% Callback functions
function DndCallback(jSource,jEvent,obj)
if jEvent.isa('java.awt.dnd.DropTargetDropEvent')
% Drop event
try
switch jSource.getDropType()
case 0
% No success.
case 1
% String dropped.
string = char(jSource.getTransferData());
if ~isempty(obj.DropStringFcn)
evt = struct();
evt.DropType = 'string';
evt.Data = string;
feval(obj.DropStringFcn,obj,evt);
end
case 2
% File dropped.
files = cell(jSource.getTransferData());
if ~isempty(obj.DropFileFcn)
evt = struct();
evt.DropType = 'file';
evt.Data = files;
feval(obj.DropFileFcn,obj,evt);
end
end
% Set dropComplete
jEvent.dropComplete(true);
catch ME
% Set dropComplete
jEvent.dropComplete(true);
rethrow(ME)
end
elseif jEvent.isa('java.awt.dnd.DropTargetDragEvent')
% Drag event
action = java.awt.dnd.DnDConstants.ACTION_COPY;
jEvent.acceptDrag(action);
end
end
end
methods (Static)
function defaultDropFcn(src,evt)
%DEFAULTDROPFCN Default drop callback.
% DEFAULTDROPFCN(src,evt) accepts the following arguments:
% src - The dndcontrol object.
% evt - A structure with fields 'DropType' and 'Data'.
fprintf('Drop event from %s component:\n',char(src.Parent.class()));
switch evt.DropType
case 'file'
fprintf('Dropped files:\n');
for n = 1:numel(evt.Data)
fprintf('%d %s\n',n,evt.Data{n});
end
case 'string'
fprintf('Dropped text:\n%s\n',evt.Data);
end
end
function [dndobj,hFig] = demo()
%DEMO Demonstration of the dndcontrol class functionality.
% dndcontrol.demo() runs the demonstration. Make sure that the
% Java class is visible in the Java classpath.
% Initialize Java class
dndcontrol.initJava();
% Create figure
hFig = figure();
% Create Java Swing JTextArea
jTextArea = javaObjectEDT('javax.swing.JTextArea', ...
sprintf('Drop some files or text content here.\n\n'));
% Create Java Swing JScrollPane
jScrollPane = javaObjectEDT('javax.swing.JScrollPane', jTextArea);
jScrollPane.setVerticalScrollBarPolicy(jScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
% Add Scrollpane to figure
[~,hContainer] = javacomponent(jScrollPane,[],hFig);
set(hContainer,'Units','normalized','Position',[0 0 1 1]);
% Create dndcontrol for the JTextArea object
dndobj = dndcontrol(jTextArea);
% Set Drop callback functions
dndobj.DropFileFcn = #demoDropFcn;
dndobj.DropStringFcn = #demoDropFcn;
% Callback function
function demoDropFcn(~,evt)
switch evt.DropType
case 'file'
jTextArea.append(sprintf('Dropped files:\n'));
for n = 1:numel(evt.Data)
jTextArea.append(sprintf('%d %s\n',n,evt.Data{n}));
end
case 'string'
jTextArea.append(sprintf('Dropped text:\n%s\n',evt.Data));
end
jTextArea.append(sprintf('\n'));
end
end
end
end
I am really stuck in here, i need to know how to gives routes for static file. I have static file in the root folder of project not in public
I tried this
GET /dump.txt controllers.Assets.at(path=".", "dump.txt")
gives me: Compilation error, Identifier expected
code that generates file:
val pw = new PrintWriter(new File("dump.txt"))
val result = Json.parse(qdb.sourceSystem(request.session("role")))
val source_system = (result \ "source_system").get.as[List[String]]
for (x ← source_system) {
try {
// val flagedJsonData = Json.parse(qdb.getSourceLineagesFromDBFlag(x, request.session("role")))
// val flagData = (flagedJsonData \ "flaglist").get.as[String]
val flagData = qdb.getSourceLineagesFromDBFlag(x, request.session("role"))
if (flagData.isEmpty == false) {
val myarray = flagData.split(",")
for (variable ← myarray) {
var dump = variable.split("::") map { y ⇒ "\"%s\"".format(y) } mkString ","
dump = "\"%s\",".format(x) + dump
pw.write(dump + "\n")
}
}
} catch {
case _: Throwable ⇒ println("Data Not Found for " + x)
}
}
pw.close
The Play docs address this well. I am assuming that you are using Play 2.x.x
You will need to add an extra route in your routes.conf file that maps to the special Assets controller. The at method will let you specify which physical file you want it to route to. If it's in your root folder, you shouldn't need to use any path spec.
Assets controller is for the serving "Assets" i.e. public static files.
You are trying to serve not public file that looks like dynamic file (name "dump" looks like you plan to do dumps time to time, so it's not seems to be static).
So, if you sure that your file is "asset" i.e. public and static then you need to put it in to the project "public" folder or subfolder and use controllers.Assets as you describe or as it is documented
In the case if you want to serve not public file that is dynamic, you need to create your own controller. I will show you a little example - you can take it and go:
app/controllers/Static.scala
package controllers
import play.api._
import play.api.mvc._
import scala.io.Source
import play.api.Play.current
class Static extends Controller {
def file(path: String) = Action {
var file = Play.application.getFile(path);
if (file.exists())
Ok(Source.fromFile(file.getCanonicalPath()).mkString);
else
NotFound
}
}
in the routs
GET /build.sbt controllers.Static.file(path="build.sbt")
result in the browser http://localhost:9000/build.sbt
name := """scala-assests-multy"""
version := "1.0-SNAPSHOT"
lazy val root = (project in file(".")).enablePlugins(PlayScala)
scalaVersion := "2.11.6"
libraryDependencies ++= Seq(
jdbc,
cache,
ws,
specs2 % Test
)
resolvers += "scalaz-bintray" at "http://dl.bintray.com/scalaz/releases"
// Play provides two styles of routers, one expects its actions to be injected, the
// other, legacy style, accesses its actions statically.
routesGenerator := InjectedRoutesGenerator
You can take this controller and use it for the serving your dump file with the
GET /dump.txt controllers.Static.file(path="dump.txt")
This is how I bootstrap my SPA.
class Bootstrap extends Controller {
def index = Assets.at("/public", "app/index.html")
}
For SPA static assets, I just make sure they're visible from my routes.
GET / controllers.Bootstrap.index
GET /views/*file controllers.Assets.versioned(path="/public/app/js/views", file: Asset)
GET /*file controllers.Assets.versioned(path="/public/app", file: Asset)
Here is an example:
/*
* Copyright 2013 ScalaFX Project
* All right reserved.
*/
package scalafx.ensemble.example.charts
import scalafx.application.JFXApp
import scalafx.scene.Scene
import scalafx.collections.ObservableBuffer
import scalafx.scene.chart.LineChart
import scalafx.scene.chart.NumberAxis
import scalafx.scene.chart.XYChart
/** A chart in which lines connect a series of data points. Useful for viewing
* data trends over time.
*
* #see scalafx.scene.chart.LineChart
* #see scalafx.scene.chart.Chart
* #see scalafx.scene.chart.Axis
* #see scalafx.scene.chart.NumberAxis
* #related charts/AreaChart
* #related charts/ScatterChart
*/
object BasicLineChart extends JFXApp {
stage = new JFXApp.PrimaryStage {
title = "Line Chart Example"
scene = new Scene {
root = {
val xAxis = NumberAxis("Values for X-Axis", 0, 3, 1)
val yAxis = NumberAxis("Values for Y-Axis", 0, 3, 1)
// Helper function to convert a tuple to `XYChart.Data`
val toChartData = (xy: (Double, Double)) => XYChart.Data[Number, Number](xy._1, xy._2)
val series1 = new XYChart.Series[Number, Number] {
name = "Series 1"
data = Seq(
(0.0, 1.0),
(1.2, 1.4),
(2.2, 1.9),
(2.7, 2.3),
(2.9, 0.5)).map(toChartData)
}
val series2 = new XYChart.Series[Number, Number] {
name = "Series 2"
data = Seq(
(0.0, 1.6),
(0.8, 0.4),
(1.4, 2.9),
(2.1, 1.3),
(2.6, 0.9)).map(toChartData)
}
new LineChart[Number, Number](xAxis, yAxis, ObservableBuffer(series1, series2))
}
}
}
}
object Main {
BasicLineChart.main(Array(""))
}
What I send the line BasicLineChart.main(Array("")) to the console, a JavaFx window shows up with a line chart in it, and the console is blocked. When I close the chart window, I recover access to scala console. When I try to fire up the same window again, I get an error:
scala> BasicLineChart.main(Array(""))
java.lang.IllegalStateException: Application launch must not be called more than once
at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:162)
at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:143)
at javafx.application.Application.launch(Application.java:191)
at scalafx.application.JFXApp$class.main(JFXApp.scala:242)
at BasicLineChart$.main(<console>:23)
... 35 elided
So I have two questions:
How to launch a JavaFx app in the console without blocking?
How to avoid the above error?
Update 1
Following some advice from freenode, I changed the BasicLineChart into a class and did this:
object Main {
val x = new BasicLineChart()
x.main(Array(""))
val y = new BasicLineChart()
y.main(Array(""))
}
Still got the same error.
On question 2, from a quick look at JFXApp it calls through to javafx.application.Application.launch, docs here. That page describes the life cycle, indicating that launch must only be called once. Basically JFXApp expects to be the entry point for a whole application, so shouldn't be called multiple times.
If you want to be able to quickly relaunch your app, I would consider just running it from SBT using run or runMain rather than using the console.
On question 1, if you do decide to run from SBT you should be able to fork in run, there are details in the SBT docs, specifically try adding fork in run := true to build.sbt.