2014-02-12 1 views
2

저는 스칼라를 처음 접했지만 아주 배우기 쉬운 언어처럼 보입니다. 현재 저는 언어를 배우기 위해 다양한 간단한 응용 프로그램을 연구하고 있습니다. 기본적인 문법부터 네트워킹까지, 저는 언어와 라이브러리가 어떻게 작동하는지에 대해 확고한 이해를 얻으려고 노력하고 있습니다.스칼라 GUI - 이벤트 처리

현재로서는 간단한 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 메소드에는 몇 가지 다른 문제 중에서 채워진 매개 변수가 없다는 것을 알았지 만, 시행 착오를 겪은 순간이었습니다. 버전이 필요하지 않을 수 있습니다.

답변

2

일반적으로 귀하의 접근 방법은 정확합니다. 그러나 listenTo 메소드를 사용할 때는 올바른 게시자를 사용해야합니다. 당신이 다음을 작성하는 경우 예를 들어, 입력 할 수 '1' "1"표시와 버튼이 집중되는 경우 :

listenTo(calculator.btn1.keys) 

주요 이벤트

특수 출판사 .keys 아니라 구성 요소에 의해 파견 그 자체.

그래서 여기에 가장 쉬운 방법은 스윙에서

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

각각 계산기의 모든 구성 요소를 듣고 수 (모든 버튼 및 패널) 것, 키 이벤트가 자동으로 버블 링되지 않습니다 포커스가있는 컴퍼넌트에 대해서만 dispatch됩니다. key-bindings라고 불리는 (Java) Swing의 또 다른 방법이 있습니다. 개요를 참조하십시오

당신은 활성 창의 아무 곳이나 누른 키를 수신하는 두 번째 방법을 사용할 수 있습니다. 그러나 Scala 초보자는 Scala 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() 
+0

: 1. "글로벌"청취자를 위해, 당신은 프레임의 모든 구성 요소를 나열해야합니다. 2. 키 바인딩을 만들려면 수행 할 작업을 지정하는 키와 함께 입력 소스를 보유하는 맵을 만들어야합니다. 액션이 호출 될 때마다 어떤 키가 눌 렸는지 확인하고 연관된 키를 사용하여 액션을 수행합니다. 여러 대학 과정에서 Java 사용에 관한 매우 일반적인 지식이 있습니다. 내가 가진 유일한 문제는 스칼라에 그것을 통합하는 것이다. 나는 이전의 "언어 간"경험이 없으므로 코드를 혼합하는 것을 협박합니다. 도움 주셔서 감사합니다. – Stalin4Time

+1

@ Stalin4Time 예. 맞습니다. Javax Swing을 배우고 싶지 않으면 포커스를 얻는 모든 구성 요소를 청취해야합니다. 대안은 최상위 구성 요소 만 듣고 키 바인딩 (입력 맵)을 사용해야합니다. 현재 입력 - 맵 기능은 Scala 래퍼 레이어에 직접 구현되지 않습니다. –