我对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方法没有填写其他一些问题的参数,但这是在经历了一些令人恼火的试错时刻之后,我想发布了多个版本可能不需要。
答案 0 :(得分:2)
您的方法通常是正确的。但是,在使用listenTo
方法时,您必须使用正确的发布者。例如,如果您编写以下内容,则当标记为“1”的按钮聚焦时,您可以键入“1”:
listenTo(calculator.btn1.keys)
关键事件由特殊发布者.keys
发送,而不是组件本身。
所以这里最简单的方法是听取计算器的每个组成部分(所有按钮和面板)
listenTo(calculator.btn1.keys, calculator.btn2.keys, ...)
在Swing中,关键事件不会自动冒泡组件层次结构,而只会被调度到具有焦点的组件。 (Java)Swing中有一种替代方法,称为键绑定。有关概述,请参阅:
您可以使用第二种方法来监听活动窗口中任何位置按下的键。但是,作为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()