27 kwietnia 2012

Aplikacje graficzne dynamicznie w Scali

Do Euro 2012 coraz bliżej, a ja coraz bardziej pewnie czuję się w Scali. Nie staram się poznawać tego języka zgodnie z jakimkolwiek wzorcem, a jedynie, jak coś wpadnie mi w ręce, to sobie przeczytam i popróbuję się z tym w Scala REPL. Na chwilę obecną jest więcej "popróbuję" nad "poczytam".

Zanim jednak o Scali...

Jutro (sobota, 28 kwietnia) prowadzę zajęcia w ramach Studiów podyplomowych studiów ITB (Informatyczne Technologie Biznesowe) na Wydziale Matematyki i Informatyki Uniwersytetu im. Adama Mickiewicza w Poznaniu. Będę mówił o różnych rzeczach wspieranych w ramach rodziny IBM WebSphere. I z tego powodu dotarłem dzisiaj do Poznania.

Podczas wysiadania z pociągu zobaczyłem, że pewna kobieta (nazwijmy ją roboczo KOBIETA) męczy się z dosyć sporawą walizą, więc zaoferowałem swoją pomoc. I tak się to dalej potoczyło.

JA: Czy mógłbym Pani pomóc?
KOBIETA: Nie, dziękuję. Brat mi pomoże.
JA: W porządku.

Podchodzi w tym momencie brat (roboczo nazwany BRAT) i patrzy na mnie jakoś dziwnie. Myślę sobie, gość mi zaraz spuści łomot za to, że dostawiam się do jego siostry. Wydawał się być zdeterminowany, aby to zrobić.

Po chwili, już poza pociągiem, kiedy ja zdejmowałem bluzę na pobliskiej ławce, na peronie.

Stanowczym krokiem nadchodzi brat. Myślę sobie, no to się zaczęło.

BRAT: Czy Ty jesteś Jacek?
JA: Tak. (zdumiony i prawie zlany potem)
BRAT: Czy Ty jesteś Jacek Laskowski?
JA: Tak. (coraz bardziej zaskoczony obrotem sytuacji, pamiętając o czujności)
BRAT: Znam Cię! Ja też jestem programistą!
JA: O, to miłe. Cześć!

I BRAT odszedł do KOBIETA zostawiając mnie w niezłym szoku. Ale pozbierałem się, przypomniałem sobie, że to nie szok, ale ego powinno teraz mną kierować i od razu zrobiło się przyjemniej :)

A wracając do Scali...

Dzisiaj czytając kolejny rozdział książki Real-World Functional Programming (With examples in F# and C#) zatytułowany "11. Refactoring and testing functional programs" przypomniałem sobie o Scali i jej REPL, i zacząłem zastanawiać się, czy mógłbym zbudować aplikację GUI dynamicznie, podobnie jak to miało ostatnimi czasy miejsce z Clojure. Jakież było moje zdumienie, kiedy niewiele trzeba mi było, aby coś zbudować. I pojawiło się okienko. A później przycisk.

Poniżej moja sesja. Zachęcam do samodzielnego popróbowania się z interpreterem scala, bo nie wymaga wiele, a sprawia niemało radochy. Ach, dodatkowo na portalu scala.net.pl pojawił się artykuł Grzegorza Balcerka zatytułowany "Metody i funkcje" i wiele się wyjaśniło. Bardzo pomocny artykuł! Zachęcam do spróbowania się z nim (aka "przeczytania") również. Czas nie będzie stracony. A jak się jeszcze wahasz, to możemy się umówić, że następny mój wpis ominiesz, aby mieć więcej czasu na artykuł :)
$ scala
Welcome to Scala version 2.10.0-M2 (OpenJDK 64-Bit Server VM, Java 1.8.0-jdk8-b35).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import javax.swing._
import javax.swing._

scala> val frame = JFrame(title="Hello")
<console>:10: error: object javax.swing.JFrame is not a value
       val frame = JFrame(title="Hello")
                   ^

scala> val frame = new JFrame(title="Hello")
<console>:10: error: overloaded method constructor JFrame with alternatives:
  (String,java.awt.GraphicsConfiguration)javax.swing.JFrame <and>
  (String)javax.swing.JFrame <and>
  (java.awt.GraphicsConfiguration)javax.swing.JFrame <and>
  ()javax.swing.JFrame
 cannot be applied to (title: String)
       val frame = new JFrame(title="Hello")
                   ^

scala> val frame = new JFrame("Hello")
frame: javax.swing.JFrame = javax.swing.JFrame[frame0,0,22,0x0,invalid,hidden,layout=java.awt.BorderLayout,
title=Hello,resizable,normal,defaultCloseOperation=HIDE_ON_CLOSE,rootPane=javax.swing.JRootPane[,0,0,0x0,
invalid,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=16777673,
maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]

scala> frame.setSize(200, 200)

scala> frame.setVisible(true)

scala> val btnOk = new JButton("Press me")
btnOk: javax.swing.JButton = javax.swing.JButton[,0,0,0x0,invalid,alignmentX=0.0,alignmentY=0.5,
border=com.apple.laf.AquaButtonBorder$Dynamic@443385ae,flags=288,maximumSize=,minimumSize=,preferredSize=,
defaultIcon=,disabledIcon=,disabledSelectedIcon=,margin=javax.swing.plaf.InsetsUIResource[top=0,left=2,
bottom=0,right=2],paintBorder=true,paintFocus=true,pressedIcon=,rolloverEnabled=false,rolloverIcon=,
rolloverSelectedIcon=,selectedIcon=,text=Press me,defaultCapable=true]

scala> frame add btnOk
res2: java.awt.Component = javax.swing.JButton[,0,0,0x0,invalid,alignmentX=0.0,alignmentY=0.5,
border=com.apple.laf.AquaButtonBorder$Dynamic@443385ae,flags=288,
maximumSize=,minimumSize=,preferredSize=,defaultIcon=,disabledIcon=,disabledSelectedIcon=,
margin=javax.swing.plaf.InsetsUIResource[top=0,left=2,bottom=0,right=2],paintBorder=true,paintFocus=true,
pressedIcon=,rolloverEnabled=false,rolloverIcon=,rolloverSelectedIcon=,selectedIcon=,text=Press me,
defaultCapable=true]

scala> frame pack
A później natrafiłem na twitterze wzmiankę o :reset w Scala REPL i byłem niezwykle uradowany mogąc od razu spróbować tego w działaniu. Użyteczne, nie powiem.
scala> :reset
Resetting interpreter state.
Forgetting this session history:

import javax.swing._
val frame = new JFrame("Hello")
frame.setVisible(true)
frame.setSize(200, 200)
val btnOk = new JButton("Press me")
frame add btnOk
frame pack

Forgetting all expression results and named terms: btnOk, frame

scala> frame
<console>:8: error: not found: value frame
              frame
              ^