Java Scala GUI-事件处理
我对Scala很陌生,但它似乎是一门非常有趣的语言,我很想学习。目前,我一直在开发各种简单的应用程序来学习这门语言。从基本语法到网络等等,我只是想牢牢掌握语言和库是如何工作的 现在,我正在使用一个简单的GUI计算器。构建GUI相当简单,我对它的实际可视化组件没有任何疑虑。问题在交互部分。出于某种原因,我不知道如何通过按键来实现某种全球关注。这可能是一个糟糕的表达方式,但这就是我的意思。我无法让程序响应我的按键,除非程序第一次打开。我相信问题在于焦点在哪里,但我不明白 以下是我的(稍微精简)代码: 我很抱歉代码太草率,但正如我所说的,我只是快速地做了一些事情。这方面的工作已经进行了几天,只需测试各种代码选项并搜索互联网 有什么帮助吗Java Scala GUI-事件处理,java,swing,scala,events,user-interface,Java,Swing,Scala,Events,User Interface,我对Scala很陌生,但它似乎是一门非常有趣的语言,我很想学习。目前,我一直在开发各种简单的应用程序来学习这门语言。从基本语法到网络等等,我只是想牢牢掌握语言和库是如何工作的 现在,我正在使用一个简单的GUI计算器。构建GUI相当简单,我对它的实际可视化组件没有任何疑虑。问题在交互部分。出于某种原因,我不知道如何通过按键来实现某种全球关注。这可能是一个糟糕的表达方式,但这就是我的意思。我无法让程序响应我的按键,除非程序第一次打开。我相信问题在于焦点在哪里,但我不明白 以下是我的(稍微精简)代码:
编辑:作为一个简要说明,我意识到listenTo方法在其他一些问题中没有填充参数,但这是在经过了一些令人恼火的尝试和错误时刻之后,我认为可能不需要发布多个版本。您的方法通常是正确的。但是,在使用
listenTo
方法时,必须使用正确的发布者。例如,如果您编写以下内容,则当标签为“1”的按钮处于焦点时,您将能够键入“1”:
listenTo(calculator.btn1.keys)
密钥事件由特殊发布者.keys
而不是组件本身发送
因此,这里最简单的方法是聆听计算器的每个组件(所有按钮和面板)
在Swing中,键事件不会自动在组件层次结构中冒泡,而只会被分派到具有焦点的组件。在(Java)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()
我从你的帖子中得到:1。要拥有“全局”侦听器,必须列出框架中的每个组件。2.要进行键绑定,您必须创建一个包含输入源的映射以及一个指定要执行的操作的键。每次调用操作时,它都会检查按下了什么键,并使用相关键执行操作。我在多个大学课程中对Java的使用有着非常广泛的了解。我唯一的问题是将它集成到Scala中。我以前没有“跨语言”的经验,所以混合代码有点吓人。非常感谢你的帮助@斯大林时间是正确的。如果您不想深入研究javaxswing,那么您将不得不倾听可能获得关注的每个组件。另一种方法是只侦听最顶层的组件,但随后必须使用键绑定(输入映射)。目前,输入映射功能没有直接在Scala包装层中实现。
listenTo(calculator.btn1.keys, calculator.btn2.keys, ...)
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()