6

I'm experimenting with a bit of Scala gui programming (my first project in scala, so I thought I'd start with something simple). But I seem to have got stuck at something that seems like it should be relatively trivial. I have a class that extends scala.swing.MainFrame, and I'd like to detect when a user presses a key when that window has focus. Funny thing is I don't seem to be able to find any way to get that event to fire.

I found an example of how someone else had got around the problem here: http://houseofmirrors.googlecode.com/svn/trunk/src/src/main/scala/HouseGui.scala but they seem to have reverted to using the Java Swing API, which is a little disappointing. Does anyone know if there's a more idiomatic way of intercepting events?

Ceilingfish
  • 5,397
  • 4
  • 44
  • 71

5 Answers5

6

This seems to work with Scala 2.9

package fi.harjum.swing

import scala.swing._
import scala.swing.event._
import java.awt.event._

object KeyEventTest extends SimpleSwingApplication {
    def top = new MainFrame {
        val label = new Label {
            text = "No click yet"
        }
        contents = new BoxPanel(Orientation.Vertical) {
            contents += label
            border = Swing.EmptyBorder(30,30,10,10)
            listenTo(keys)
            reactions += {
                case KeyPressed(_, Key.Space, _, _) =>
                    label.text = "Space is down"
                case KeyReleased(_, Key.Space, _, _) =>
                    label.text = "Space is up"
            }
            focusable = true
            requestFocus
        }
    }
}      
Mika Harju
  • 69
  • 1
  • 2
3

In addition to listening to this.keys you should also call requestFocus on the component or set focusable=true, if it is Panel or derived class.

Oleg
  • 31
  • 4
1

I expect you need to listen to this.keys (where this is the element of the GUI receiving the keyboard events). See the equivalent question about mouse event.

Community
  • 1
  • 1
Daniel C. Sobral
  • 295,120
  • 86
  • 501
  • 681
  • Thx Daniel, I needed this too. The scala's swing documentation is really poor. – Aymen Jun 29 '10 at 04:47
  • `this.keys` doesn't seem to be a valid attribute of `scala.swing.MainFrame`. Nor does `this.Keys`, `this.Keyboard` or `this.keyboard`. Is there any documentation on this anywhere? – Ceilingfish Jun 29 '10 at 08:57
  • @Ceilingfish Not the `MainFrame`, but a `Component`: labels, panels, text areas, etc. And, of course, `this` refers to the component itself. – Daniel C. Sobral Jun 29 '10 at 13:42
1

My solution for this required me to do the following:

class MyFrame extends MainFrame {

this.peer.addKeyListener(new KeyListener() {
    def keyPressed(e:KeyEvent) {
      println("key pressed")
    }

    def keyReleased(e:KeyEvent) {
      println("key released")
    }

def keyTyped(e:KeyEvent) {
      println("key typed")
    }
 })

}

This only seemed to work though if there were no button objects attached to this component, or any of it's children.

Ceilingfish
  • 5,397
  • 4
  • 44
  • 71
0

Rather than falling back to java events all components have keys that publishes these events (so MainFrame does not). Not sure what the best solution is but it's always possible to wrap everything in the frame inside a Component and listen to its keys.

Adam Bergmark
  • 7,316
  • 3
  • 20
  • 23