package pGrid
package pUIFx
import pUtil._
object DevAppFx extends AppFx
{
println("Begining DevFxApp object constructor in package pGrid.pUIFx")
//devStart
}
package pGrid
package pUIFx
import pGeom._
import pGrid.pDev._
import scalafx.application._
import scalafx.application.JFXApp._
import scalafx.scene._
import scalafx.scene.paint._
class AppFx extends JFXApp with DevTr
{
println("Creating stage")
stage = new PrimaryStage
{
x = 3850
y = 200
width = 1000
height = 800
scene = new Scene
}
def openEFO(de: DescEFlatOne): Unit =
{
println("def in AppFx")
stage.scene = ScrEditFx(stage, de)
}
}
The DevAppFx object constructor runs, including the println ("Beginning ...
The class AppFx constructor does not run including the println ("creating stage"). The openEFO method can be called but the stage variable is null.
Edit this is a simplification. There will be a lot more functionality in DEVAppFx and AppFx, so its important to be able to keep the functionality separate.
I think the issue here is that scalafx.application.JXFApp is a class that extends the scala.DelayedInit trait. As such, some Scala magic happens under the hood: see the scala.DelayedInit docs for more. Unfortunately, DelayedInit is buggy and plays havoc with sub-class initialization/construction code - such as your AppFx class not executing its constructor.
There's no easy solution to this, I'm afraid. Until the DelayedInit behavior is resolved, or until we find a better way to initialize ScalaFX, your best bet is to merge DevAppFx and AppFx into a single object, which should work as expected.
For example:
package pGrid
package pUIFx
import pGeom._
import pGrid.pDev._
import scalafx.application._
import scalafx.application.JFXApp._
import scalafx.scene._
import scalafx.scene.paint._
object AppFx extends JFXApp with DevTr
{
println("Creating stage")
stage = new PrimaryStage
{
x = 3850
y = 200
width = 1000
height = 800
scene = new Scene
}
// Relocate DevAppFx init here...
println("Begining DevFxApp object constructor in package pGrid.pUIFx")
//devStart
def openEFO(de: DescEFlatOne): Unit =
{
println("def in AppFx")
stage.scene = ScrEditFx(stage, de)
}
}
UPDATE:
I did some more digging around, and scalafx.application.JFXApp didn't do a great job of implementing the semantics of the scala.DelayedInit trait. In essence, it was only storing the construction/initialization code of the class/object at the bottom of the inheritance hierarchy, and dropping everything else. For further details, there is a ScalaFX bug report for this issue.
So, in your example, the construction code for the object DevAppFx was replacing the construction code for your class AppFx, instead of storing both, resulting in the symptoms you observed.
I've committed a patch to the default and SFX-8 branches of ScalaFX on Google Code, which you're free to utilize. Alternatively, if you're prepared to wait a few weeks, the next updates published to the Sonatype OSS to have the patch will be 1.0.0-R9 (for the JavaFX 2 equivalent) and 8.0.0-R5 (for the JavaFX 8 equivalent).
This patch should allow your original code to run unmodified. If you get a chance to try it out, let me know how you get on...
I've use the information about possible bugs in DelayedInit from Mike Allen's answer. However I want to keep the functionality separate rather than combining it into one object. Reading the docs, the problem is with classes and Objects not with traits that inherit from JFXApp and DelayedInit, so I have converted AppFx into a trait and moved the Stage creation into a method
object DevAppFx extends AppFx with DevTr
{
openStage
devStart
}
____________--
trait AppFx extends JFXApp with StratApp
{
def openStage: Unit = stage = new PrimaryStage
{
x = 3850
y = 200
width = 1000
height = 800
scene = new Scene
}
override def openEFO(de: DescEFlatOne): Unit = stage.scene = ScrEditFx(this, de)
}
Related
i originally made scripts with many functions on 2 individual scala worksheets. i got them working and now want to tie these individual scripts together by importing and using them into a third file. from what i have read you can not simply import external scripts you must first make them into a class and put them into a package. so i tried that but i still couldn't import it
i know this may be a bit basic for this site but im struggling to find much scala documentation.
i think my problem might span from a missunderstanding of how packages work. the picture below might help.
my program example
adder.scala
package adder
class adder {
def add_to_this(AA:Int):Int={
var BB = AA + 1;
return BB
}
}
build.scala
package builder
class build {
def make_numbers(){
var a = 0;
var b = 0;}
}
main.sc
import adder
import builder
object main {
adder.adder.add_to_this(10);
}
the errors i get are
object is not a member of package adder
object is not a member of package builder
Classes in scala slightly differ from classes in java. If you need something like singleton, you'll want to use object instead of class i.e.:
package com.example
object Main extends App {
object Hide{
object Adder{
def addToThis(AA:Int):Int = AA + 1
}
}
object Example{
import com.example.Main.Hide.Adder
def run(): Unit = println(Adder.addToThis(10))
}
Example.run()
}
Consider objects like packages/modules which are also regular values. You can import an object by its full path, i.e. com.example.Main.Hide.Adder you can also import contents of an object by adding .{addToThis}, or import anything from object by adding ._ after an object.
Note that classes, traits and case classes could not be used as objects, you can't do anything with it unless you have an instance - there are no static modifier.
I'm trying to import an object from another .scala file that doesn't exist inside a class. I've found you can import a class like in here Scala, importing class. Is there a way to import an object without having a class around it?
Thanks
Importing a class and importing an object work the same in scala.
If you have a class
package com.package1
class MyClass{}
and an object
package com.package2
object MyObject{}
You import both the exact same way
package com.package3
import com.package1.MyClass
import com.package2.MyObject
import syntax is the same no matter what you are importing, whether it's an object, a class, a trait, a method, or a field
Yes, Scala can do exactly what you ask, and this is used frequently. Here is an example:
object Blah {
val x = 1
val y = "hello"
}
object Main extends App {
import Blah._
println(s"x=$x; y=$y")
}
Output is:
x=1; y=hello
You can also import members of a class instance, which blew my mind the first time I saw it.
If you are talking about companion objects, they are not defined inside a class, but after the class definition:
class AClass {
def sayHello() = {
println(AClass.Hello)
}
}
object AClass {
private val Hello = "hello"
}
You should have no problem importing it.
I've inherited a Scala project that has to be extended and instead of one monolithic monster it has to be split: some code needs to become a library that's used by all the other components and there's a few applications that may be included at some later point.
object Shared {
// vals, defs
}
=====
import Shared._
object Utils1 {
// vals, defs
}
=====
import Shared._
object Utils2 {
// vals, defs
}
=====
import Shared._
import Utils1._
class Class1(val ...) {
// stuff
}
=====
import Shared._
import Utils2._
class Class2(val ...) {
// more stuff
}
etc.
The problem is that Utils1 and Utils2 (and many other objects and classes) use the values from Shared (the singleton) and that Shared now has to be instantiated because one of the key things that happens in Shared is that the application name is set (through SparkConf) as well as reading of configuration files with database connection information.
The idea was to have a multi-project build where I can just pick which component needs to be recompiled and do it. Since the code in Utils is shared by pretty much all applications that currently exist and will come, it's nice to keep it together in one large project, at least so I thought. It's hard to publish to a local repository the code that's common because we have no local repository (yet) and getting permission to have one is difficult.
The Utils singletons are needed because they have to be static (because of Spark and serializability).
When I make Shared a proper class, then all the import statements will become useless and I have to pass an instance around, which means I cannot use singletons, even though I need those. It currently works because there is only a single application, so there really only one instance of Shared. In future, there will still be only one instance of Shared per application but there may be multiple applications/services defined in a single project.
I've looked into implicits, package objects, and dependency injection but I'm not sure that's the right road to go down on. Maybe I'm just not seeing what should be obvious.
Long story short, is there a neat way to give Shared a parameter or achieve what I hope to achieve?
Maybe as an option you can create SharedClass class and make Shared object extend it in each app with different constructor params:
class SharedClass(val param: String) { // vals ...
}
object Shared extends SharedClass("value")
One hacky way to do it, is to use a DynamicVariable and make it have a value, when Shared is initialized (i.e., the first time anything that refers to Shared fields or methods is called).
Consider the following:
/* File: Config.scala */
import scala.util.DynamicVariable
object Config {
val Cfg: DynamicVariable[String] = new DynamicVariable[String](null)
}
/**********************/
/* File: Shared.scala */
import Config._
object Shared {
final val Str: String = Cfg.value
def init(): Unit = { }
}
/*********************/
/* File: Utils.scala */
import Shared._
object Utils {
def Length: Int = Str.length
}
/********************/
/* File: Main.scala */
object Main extends App
{
// Make sure `Shared` is initialized with the desired value
Config.Cfg.withValue("foobar") {
Shared.init()
}
// Now Shared.Str is fixed for the duration of the program
println(Shared.Str) // prints: foobar
println(Utils.Length) // prints: 6
}
This setup is thread-safe, although not deterministic, of course. The following Main would randomly select one of the 3 strings, and print the selected string and its length 3 times:
import scala.util.Random
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
object Main extends App
{
def random(): Int = Random.nextInt(100)
def foo(param: String, delay: Int = random()): Future[Unit] = {
Future {
Thread.sleep(delay)
Config.Cfg.withValue(param) {
Shared.init()
}
println(Shared.Str)
println(Utils.Length)
}
}
foo("foo")
foo("foobar")
foo("foobarbaz")
Thread.sleep(1000)
}
object in Scala has "apply" method which you can use for this purpose. So, your Shared object will be like below
object Shared {
def apply(param1: String, param2: String) = ???
}
Now each client of Shared can pass different values.
I just started to write scalafx application and have a question about bindings.
I have an Enumeration with connection status in my presenter class and I want to select appropriate icon in label in view class. I basically can create binding in javafx way and set converter which will select appropriate ImageView every time status changes, but is it possible to do in ScalaFX way?
I looked many scalafx examples, but still can't find anything like this.
Here is some code:
package view
import scalafx.beans.property.ObjectProperty
class MainWindowPresenter {
object DatabaseState extends Enumeration {
type DatabaseState = Value
val NOT_CONNECTED, IDLE, BUSY, ERROR = Value
}
val login = new ObjectProperty[String](this, "login", "awesomeloginname")
val state = new ObjectProperty[DatabaseState.DatabaseState](this, "state", DatabaseState.ERROR)
}
View class:
package view
import java.util.concurrent.Callable
import javafx.beans.binding.ObjectBinding
import collection.immutable.HashMap
import javafx.scene.control.SeparatorMenuItem
import scala.util.Random
import scalafx.beans.property.{ObjectProperty}
import scalafx.geometry.{Orientation, Insets, Pos}
import scalafx.scene.control._
import scalafx.scene.image.{ImageView, Image}
import scalafx.scene.layout._
import scalafx.Includes._
class MainWindowView extends BorderPane {
val model = new MainWindowPresenter
top = new HBox {
content = List(
new Label() {
graphic <== //somehow select imageview depending on model.state
}
)
}
private def imageFromResource(name : String) =
new ImageView(new Image(getClass.getClassLoader.getResourceAsStream(name)))
}
Thanks in advance and sorry for grammar mistakes, if any - English isn't my native.
You can use EasyBind or the snapshot (2.0-SNAPSHOT) version of ReactFX to create the binding. Both are Java libraries, but they are easy to use from Scala. This is the EasyBind way:
graphic <== EasyBind.map(model.state, stateToImage)
val stateToImage: Function1[DatabaseState.DatabaseState, ImageView] = {
// convert state to ImageView
}
This code uses the implicit conversion from Scala's Function1 to Java's Function.
You could also define an implicit conversion from ScalaFX ObjectProperty to EasyBind's MonadicObservableValue and then the first line above can be rewritten to:
graphic <== model.state.map(stateToImage)
I'm really new to Scala, and I've come across an error I am unable to solve by myself or through internet searches.
I have a Scala class called "GUI" that represents a JFrame along with a companion class. When I try to import the companion class using import GUI._ I get the error "stable identifier required, but GUI.this.GUI() found".
I made an empty class and companion object and the import worked fine, so I assume that the error is related to something specific to my code. Below is the code in question:
object GUI {
def test:Integer = 1
}
class GUI extends JFrame{
import GUI._
val ICON_LOCATION:File = new File("Images/iMovies.ico");
val ICON:BufferedImage = Ootil.createImage("iMovies.png");
val TITLE:String = "iVideos";
val LICENSE_NAME:String = "OpenBSD";
def GUI(){
setLayout(new BorderLayout());
createGUI();
pack();
setSize(100,100);
setLocationRelativeTo(null);
setVisible(true);
}
def versionMajor: Integer = 1
def versionMinor: Integer = 0
def versionRevision: Integer = 0
def versionPreReleaseID: String = "alpha"
def versionBuildNumber: String = "1b"
private def createGUI():Unit = {
val panel = new JPanel();
panel.setLayout(new BorderLayout());
add(panel, BorderLayout.CENTER);
}
def getIcon():BufferedImage = ICON
def getProgramTitle():String = TITLE
def getConfigOptions():LookAndFeelConfigurationOptions = GUIConfigOptions.CONFIG_OPTIONS;
}
To add to Kipton's answer, there's nothing wrong with doing:
class GUI{
def GUI() {
println("something")
}
}
But the result won't be a constructor -- it will be an ordinary method.
val a = new GUI() won't print anything, but calling a.GUI() will.
This is why you didn't get an error message about defining your constructor incorrectly.
When you run the command import GUI._, Scala needs GUI to always evaluate to the same object. This is only the case when GUI is an object, a package, or a val.
In your code, import GUI._ referred to the method GUI that you defined, because the GUI method is defined in a closer scope than object GUI (the fact that the compiler hasn't encountered the definition of def GUI yet doesn't make a difference).
Since import GUI._ referred to the method GUI, which is not a val, object, or package, you got the error message about GUI not being a stable identifier.
Welcome to the Scala community.
Scala constructors work differently than they do in Java. To fix the error, you should put the body of your previously defined GUI() method directly into the class definition, like so,
class GUI extends JFrame{
import GUI._
val ICON_LOCATION:File = new File("Images/iMovies.ico");
val ICON:BufferedImage = Ootil.createImage("iMovies.png");
val TITLE:String = "iVideos";
val LICENSE_NAME:String = "OpenBSD";
// ** stuff that used to be in method GUI() goes below **
setLayout(new BorderLayout());
createGUI();
pack();
setSize(100,100);
setLocationRelativeTo(null);
setVisible(true);
...
}
It takes a little getting used to, but I think you'll find that Scala's way is a lot nicer.
If you want to define an auxiliary constructor, declare a method def this(...) { ... } whose first expression is a call to the primary constructor (in this case just this(), since it doesn't take parameters).
If you want to add parameters to your primary constructor, you would define the class as
class GUI( << some parameters >> ) extends JFrame { ... }
and then you can use the parameters anywhere in this class body.