5

I wrote my first console app in Scala, and I wrote my first Swing app in Scala -- in case of the latter, the entry point is top method in my object extending SimpleSwingApplication.

However I would like to still go through main method, and from there call top -- or perform other equivalent actions (like creating a window and "running" it).

How to do it?

Just in case if you are curious why, the GUI is optional, so I would like to parse the command line arguments and then decide to show (or not) the app window.

greenoldman
  • 16,895
  • 26
  • 119
  • 185
  • 1
    If you use IntelliJ or similar, it's easy to Ctrl-click through to see the source of SimpleSwingApplication, which will help you understand what's going on. – Luigi Plinge Oct 26 '11 at 21:48

4 Answers4

4

Here is the most basic example:

import swing._

object MainApplication {
  def main(args: Array[String]) = {
    GUI.main(args)
 }

  object GUI extends SimpleSwingApplication {
    def top = new MainFrame {
      title = "Hello, World!"
    }
  }
}

Execute scala MainApplication.scala from the command line to start the Swing application.

Garrett Hall
  • 29,524
  • 10
  • 61
  • 76
4

If you have something like:

object MySimpleApp extends SimpleSwingApplication {
  // ...
}

You can just call MySimpleApp.main to start it from the console. A main method is added when you mix SimpleSwingApplication trait. Have a look at the scaladoc.

paradigmatic
  • 40,153
  • 18
  • 88
  • 147
  • 1
    I meant from the "traditional" main method, so the user won't spot the difference. With information from you, it was piece of cake, I simply called GUI main from the "traditional" main. Thank you! – greenoldman Oct 26 '11 at 18:41
  • Thanks. I was struggling with googling all over the place and could not figure out how to run the Artima Odersky book's GUI example (FirstSwingApp). Now I just put in my main object a line FirstSwingApp.main(args) and works fine. – G.A. Nov 18 '12 at 17:12
2

If you override the main method that you inherit from SimpleSwingApplication, you can do whatever you want:

object ApplicationWithOptionalGUI extends SimpleSwingApplication {

  override def main(args: Array[String]) =
    if (parseCommandLine(args))
      super.main(args) // Starts GUI
    else
      runWithoutGUI(args)

...

}
QFH
  • 76
  • 3
0

I needed main.args to be usable in SimpleSwingApplication. I wanted to give a filename to process as an argument in CLI, or then use JFileChooser in case the command line argument list was empty.

I do not know if there is simple method to use command line args in SimpleSwingApplication, but how I got it working was to define, in demoapp.class:

class demoSSA(args: Array[String]) extends SimpleSwingApplication {
    ....
    var filename: String = null
    if (args.length > 0) {
        filename = args(0)
    } else {
        // use JFileChooser to select filename to be processed 
        // https://stackoverflow.com/questions/23627894/scala-class-running-a-file-chooser
    }
    ....
}

object demo {
  def main(args: Array[String]): Unit = {
     val demo = new demoSSA(args)
     demo.startup(args)
  }
}

Then start the app by demo [args], by giving filename as a CLI argument or leaving it empty and program uses JFileChooser to ask it.

Is there a way to get to the args of main() in SimpleSwingApplication singleton object? Because it doesn't work to parse 'filename' in overridden SimpleSwingApplication.main and to use 'filename' in the singleton object it needs to be declared (val args: Array[String] = null;), not just defined (val args: Array[String];). And singleton objecs inherited from SSA cannot have parameters.

(Edit) Found one another way: If whole demoSSA is put inside overridden main() or startup(), then top MainFrame needs to defined outside as top = null and re-declare it from startup() as this.top:

object demo extends SimpleSwingApplication {  
  var top: MainFrame = null
  override def startup(args: Array[String]) {
    ...  // can use args here
    this.top = new MainFrame {
      ... // can use args here also
    };
    val t = this.top
    if (t.size == new Dimension(0,0)) t.pack()
      t.visible = true
  }
}

But I think I like the former method more, with separated main object.It has at least one level indentation less than the latter method.

zimon
  • 171
  • 1
  • 10