Clint, Greg,
Thanks for taking the time to look into this.
Here is the code that works:

...
import org.apache.pivot.wtk.PushButton
import org.apache.pivot.wtk.Button
...

class EnBalSP extends Application {
  var window: Window = null
...
 @BXML private var printButton: PushButton = null
...

...
  override def startup(display:Display, ns:Map[String, String]) = {
    val enBalSer: BXMLSerializer = new BXMLSerializer
...

    window = enBalSer.readObject(classOf[EnBalSP], 
"enbal.bxml").asInstanceOf[Window]
...
 enBalSer.bind(this, classOf[EnBalSP])

...
    initButtons
...
 window.open(display)
  }

...
 def initButtons = {
...
   printButton.getButtonPressListeners.add(new ButtonPressListener {
     override def buttonPressed(b: Button) {
     print
     }
     })
...
 }

...
 override def suspend() {}

  override def resume() {}

  override def shutdown(optional:Boolean):Boolean = {
    if (window != null) window.close()
    return false
  }
}

So, in the above the Application is launched, the buttons are binded with @BXML, the bxml file is deserialized in startup, which calls initButtons where the listeners are registered. The above is working. Now if I change the initButtons as shown below:

...
import org.apache.pivot.wtk.PushButton
import org.apache.pivot.wtk.Button
...

class EnBalSP extends Application {
  var window: Window = null
...
 @BXML private var printButton: PushButton = null
...

...
  override def startup(display:Display, ns:Map[String, String]) = {
    val enBalSer: BXMLSerializer = new BXMLSerializer
...

    window = enBalSer.readObject(classOf[EnBalSP], 
"enbal.bxml").asInstanceOf[Window]
...
 enBalSer.bind(this, classOf[EnBalSP])

...
    initButtons
...
 window.open(display)
  }

...
 def initButtons = {
...
    pressedDo(printButton, print)
...
 }

  def pressedDo (aB: PushButton, action: Unit) = {
    aB.getButtonPressListeners.add(new ButtonPressListener {
        override def buttonPressed(b: Button): Unit = action })

...
 override def suspend() {}

  override def resume() {}

  override def shutdown(optional:Boolean):Boolean = {
    if (window != null) window.close()
    return false
  }
}

I get the error that display is null??

It is really strange.



Clint Gilbert said the following on 23/11/2010 20:37:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Actually, the type of b is the problem:

override def buttonPressed(b: Button): Unit = action

or even

override def buttonPressed(b: Button) = action

instead of

override def buttonPressed(b: PushButton): Unit = action

is what you want.

Clint Gilbert wrote:
This is getting off-topic, but it's something I actually know a tiny bit
about.

The compiler is complaining (I think) because you're not actually
overriding buttonPressed.  This can happen when type inference goes a
little astray, especially with methods that return Unit.  Naming
buttonPressed's param 'b' shouldn't be a problem.  I'd try explicitly
specifying the return type, like

def pressedDo (aB: PushButton, action: Unit) = {
   aB.getButtonPressListeners.add(new ButtonPressListener {
     override def buttonPressed(b: PushButton): Unit = action
   })
}

There are also inference rule that take effect regarding the = in

def foo(...) = { }

vs def foo(...) { }

The latter (I believe) is assumed to return Unit, but I always add the =
just to be sure.  (/Programming Scala/ by Odersky, Venners, and Spoon
explains things like this very, very well.)

Additionally, you probably want something like this:

def pressedDo (aB: PushButton, action: =>  Unit) = {
   aB.getButtonPressListeners.add(new ButtonPressListener {
     override def buttonPressed(b: PushButton) = action
   })
}

Note the new type of the 'action' param.  It's now "a function that
takes no params and returns Unit", instead of an actual value of type
Unit.  This is an easy way to have lazily-evaluated parameters.

Due to some neat syntactic sugar for writing anonymous functions of this
type, if you split the parameter list for pressedDo, like

def pressedDo (aB: PushButton)(action: =>  Unit) = {
   aB.getButtonPressListeners.add(new ButtonPressListener {
     override def buttonPressed(b: PushButton) = action
   })
}

You could call it like:

pressedDo(someButton) {
   val foo = new Foo

   someOtherThing.doStuff(foo)

   //etc
}

Here the stuff in the braces becomes an anonymous function that gets
passed to pressedDo.

It's also possible to use implicit conversions (the perhaps
tastelessly-named "Pimp-My-Library" pattern[1]) to "add" the pressedDo
method to the Button class.  Well, kind of, not really to the Button
class, but combined with the above technique, you could make a call like

val someButton: Button = ...

someButton pressed {
   val foo = new Foo

   someOtherThing.doStuff(foo)
}

which is starting to look smooth.  Implicits can get pretty black-magic
though, so use them with care and restraint if you do.

[1]: http://scala.sygneca.com/patterns/pimp-my-library

Bojan Vu ini wrote:
Hi All,
If you are using Scala for your code then you are obliged to write listeners in 
the following way:

printButton.getButtonPressListeners.add(new ButtonPressListener {
      override def buttonPressed(b: Button) {
         print
      }
   })

I've tried to simplify this by defining the following method:
   def pressedDo (aB: PushButton, action: Unit) = {
     aB.getButtonPressListeners.add(new ButtonPressListener {
         override def buttonPressed(b: PushButton) { action }})
   }

and than invoking the method in this way (example)
     pressedDo(printButton, print)

however, this results in a compiler error:

error: object creation impossible, since method buttonPressed in trait 
ButtonPressListener of type (x$1: org.apache.pivot.wtk.Button)Unit is not 
defined
     aB.getButtonPressListeners.add(new ButtonPressListener {

I'm not a programming language specialist, and in addition a Scala novice, but 
I'm puzzled why putting boilerplate code in a separate method is not working??
Best regards,
Bojan

Dr. Bojan Vu ini
President, Ma-CAD<http://www.ma-cad.com/>
[email protected]<mailto:[email protected]>
IM: bvucinic (Skype)
http://fr.linkedin.com/in/bvucinic
Maintenance Concept Adjustment&  Design 31, rue Chanzy
Paris, Ile de France 75011 France
Work: +33 (6) 14 15 36 70
Mobile: +33 (6) 14 15 36 70
Fax: +33 (1) 53 01 38 28
See who we know in common<http://www.linkedin.com/e/wwk/4839994/>        Want a 
signature like this?<http://www.linkedin.com/e/sig/4839994/>

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkzsGBIACgkQ5IyIbnMUeTtlkwCZAUsW/ssyCxJ95PaxTbW0ap0a
RBwAn1ttMyvrnr/iLAZ8gAIPFy/g5obf
=axhA
-----END PGP SIGNATURE-----


Reply via email to