我是Scala的新手,但是它似乎是一种我想学习的非常有趣的语言。目前,我一直在研究各种简单的应用程序来学习该语言。从基本语法到网络等等,我只是想牢固地了解语言和库的工作方式。

截至目前,我正在使用一个简单的GUI计算器。构建GUI非常简单,我对它的实际视觉组件没有任何疑问。问题在交互式部分内。由于某些原因,我无法弄清楚如何通过按键实现某种全球关注。那可能是一个糟糕的措词方式,但这就是我的意思。除了程序首次打开时,我无法使程序响应按键。我认为问题出在重点所在,但我无法弄清楚。

这是我的代码(略有剥离):

package SimplePrograms

import scala.swing._
import javax.swing.{BorderFactory, UIManager}
import scala.swing.event.{Key, KeyPressed}

/**
 * Created by Tony on 2/9/14.
 */
object SimpleCalculator {
  def main(args: Array[String]){
    UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel")
    val calculator = new CalcGrid
    val frame = new MainFrame{
      title = "Calculator"
      contents = calculator.CalcPanel()
      listenTo()
      reactions += {
        case KeyPressed(_,Key.Numpad1,_,_)
        => calculator.numTxt.text += "1"
      }
      size = new Dimension(200,270)
      centerOnScreen()
      resizable = false
    }
    frame.open()
  }
}

class CalcGrid(){
  var numTxt = new TextField(" "){
    font = new Font("Arial",0,40)
    background = new Color(200,130,20)
    opaque = true
    border = BorderFactory.createCompoundBorder(
      BorderFactory.createLoweredBevelBorder(),
      BorderFactory.createEmptyBorder(0,5,0,5))
    editable = false
    horizontalAlignment = Alignment.Right
  }
  val btn1 = new Button("1"){
    font = new Font("Arial",0,20)
    background = new Color(200,130,20)
    preferredSize = new Dimension(40,35)
  }
  val btn2 = new Button("2"){
    font = new Font("Arial",0,20)
    background = new Color(200,130,20)
    preferredSize = new Dimension(40,35)
  }
  val btn3 = new Button("3"){
    font = new Font("Arial",0,20)
    background = new Color(200,130,20)
    preferredSize = new Dimension(40,35)
  }
  val btn4 = new Button("4"){
    font = new Font("Arial",0,20)
    background = new Color(200,130,20)
    preferredSize = new Dimension(40,35)
  }
  val btn5 = new Button("5"){
    font = new Font("Arial",0,20)
    background = new Color(200,130,20)
    preferredSize = new Dimension(40,35)
  }
  val btn6 = new Button("6"){
    font = new Font("Arial",0,20)
    background = new Color(200,130,20)
    preferredSize = new Dimension(40,35)
  }
  val btn7 = new Button("7"){
    font = new Font("Arial",0,20)
    background = new Color(200,130,20)
    preferredSize = new Dimension(40,35)
  }
  val btn8 = new Button("8"){
    font = new Font("Arial",0,20)
    background = new Color(200,130,20)
    preferredSize = new Dimension(40,35)
  }
  val btn9 = new Button("9"){
    font = new Font("Arial",0,20)
    background = new Color(200,130,20)
    preferredSize = new Dimension(40,35)
  }
  val btn0 = new Button("0"){
    font = new Font("Arial",0,20)
    background = new Color(200,130,20)
    preferredSize = new Dimension(40,35)
  }
  val btnPeriod = new Button("."){
    font = new Font("Arial",0,20)
    background = new Color(200,130,20)
    preferredSize = new Dimension(40,35)
  }
  val btnEqual = new Button("="){
    font = new Font("Arial",0,20)
    background = new Color(200,130,20)
    preferredSize = new Dimension(40,60)
  }
  val btnMinus = new Button("-"){
    font = new Font("Arial",0,20)
    background = new Color(200,130,20)
    preferredSize = new Dimension(40,35)
  }
  val btnPlus = new Button("+"){
    font = new Font("Arial",0,20)
    background = new Color(200,130,20)
    preferredSize = new Dimension(40,35)
  }

  def CalcPanel(): GridBagPanel = {
    val contents = new GridBagPanel(){
      var c = new Constraints()
      c.gridx = 0
      c.gridy = 0
      c.gridwidth = 4
      c.insets = new Insets(3,3,3,3)
      c.fill = GridBagPanel.Fill.Horizontal
      add(numTxt,c)

      c.gridwidth = 1
      c.fill = GridBagPanel.Fill.None

      c.gridx = 0
      c.gridy = 1
      add(btn7,c)

      c.gridx = 1
      c.gridy = 1
      add(btn8,c)

      c.gridx = 2
      c.gridy = 1
      add(btn9,c)

      c.gridx = 0
      c.gridy = 2
      add(btn4,c)

      c.gridx = 1
      c.gridy = 2
      add(btn5,c)

      c.gridx = 2
      c.gridy = 2
      add(btn6,c)

      c.gridx = 0
      c.gridy = 3
      add(btn1,c)

      c.gridx = 1
      c.gridy = 3
      add(btn2,c)

      c.gridx = 2
      c.gridy = 3
      add(btn3,c)

      c.gridx = 3
      c.gridy = 1
      add(btnMinus,c)

      c.gridx = 3
      c.gridy = 2
      add(btnPlus,c)

      c.gridx = 0
      c.gridy = 4
      c.gridwidth = 2
      c.fill = GridBagPanel.Fill.Horizontal
      add(btn0,c)
      c.gridwidth = 1
      c.fill = GridBagPanel.Fill.None

      c.gridx = 2
      c.gridy = 4
      add(btnPeriod,c)

      c.gridx = 3
      c.gridy = 3
      c.gridheight = 4
      c.fill = GridBagPanel.Fill.Vertical
      add(btnEqual,c)
    }
    contents
  }
}


我为松散的代码表示歉意,但是正如我所说,只是快速地提出了一些建议。仅仅测试各种代码选项并搜索互联网,就已经为此工作了几天。

有什么帮助吗?

编辑:作为一个简短的说明,我意识到在其他一些问题中,listenTo方法没有填写参数,但这是在经过一些令人烦恼的反复试验之后,并且我认为发布多个版本可能不是需要。

最佳答案

您的方法通常是正确的。但是,使用listenTo方法时,必须使用正确的发布者。例如,如果您编写以下内容,则当标签为“ 1”的按钮聚焦时,您将能够输入“ 1”:

listenTo(calculator.btn1.keys)


关键事件由特殊发布者.keys调度,而不是组件本身。

因此,这里最简单的方法是监听计算器的每个组成部分(所有按钮和面板)

listenTo(calculator.btn1.keys, calculator.btn2.keys, ...)




在Swing中,关键事件不会自动使组件层次结构冒泡,而只会分派给具有焦点的组件。 (Java)Swing中有另一种方法,称为键绑定。有关概述,请参见:


How to Write a Key Listener
How to Use Key Bindings


您可以使用第二种方法来侦听活动窗口中任何位置的按键。但是,作为Scala初学者,这可能会造成混淆,因为您将不得不使用Java Swing而不是Scala Swing包装层。为了完整起见,我向大家展示了一般如何做到这一点:

import javax.swing.{JComponent, KeyStroke} // Java world

val calculator = new CalcGrid
val frame = new Frame{
  title = "Calculator"
  val panel = calculator.CalcPanel()
  contents = panel
  val act1 = Action("key1") {
    calculator.numTxt.text += "1"
  }
  // the mapping is done in your top component, so `panel`.
  // you must use the input map which is active whenever the window
  // in which the panel is located has focus:
  val imap = panel.peer.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
  val amap = panel.peer.getActionMap
  // you need to map a KeyStroke to an (arbitrarily chosen) action name,
  // and that action name to the action itself.
  imap.put(KeyStroke.getKeyStroke(Key.Numpad1.id, 0), "key1")
  imap.put(KeyStroke.getKeyStroke(Key.Key1   .id, 0), "key1") // can map several keys
  amap.put("key1", act1.peer)

  size = new Dimension(200,270)
  centerOnScreen()
  resizable = false
}
frame.open()

关于java - Scala GUI-事件处理,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21734961/

10-10 21:49
查看更多