1

有没有一种方便的方法来添加过滤器以输入到 scala.swing.TextComponent,以便用户只能输入整数/浮点数/其他?特别是,有没有办法将粘贴过滤到文本字段中?在 Java 中,我使用了 DocumentFilter 来做到这一点。我已经尝试了一些变化:

object inputField extends TextField{

   peer.getDocument.asInstanceOf[AbstractDocument].setDocumentFilter(new DocumentFilter{

      def insertString(fb: FilterBypass, offs: Integer, str: String, a: AttributeSet){
         if(str.forall((c)=>c.isDigit)) super.insertString(fb, offs, str, a)
      }

      def replace(fb: FilterBypass, offs: Integer, l: Integer, str: String, a: AttributeSet){
         if(str.forall((c)=>c.isDigit)) super.replace(fb, offs, l, str, a)
      }
   })
}

这是行不通的。我做错了吗,还是 Scala 忽略了文档过滤器?还有另一种方法可以做到这一点吗?如果需要的话,我可能完全可以使用 java.swing GUI。

4

2 回答 2

2

您可以使用反应来实现这一点:

import swing._
import swing.event._

object SwingApp extends SimpleSwingApplication {
  def top = new MainFrame {
    contents = new TextField {
      listenTo(keys)
      reactions += { case e: KeyTyped =>
        if (!e.char.isDigit) e.consume
      }
    }
  }
}

更新:哦,我同意,这仅适用于相对琐碎的情况。我发现您的原始解决方案存在问题:您在需要 Ints 的地方使用整数,因此您的方法只是新方法,而不是抽象类方法的实现。这是它对我的工作方式:

contents = new TextField {
  object IntegralFilter extends DocumentFilter {
    override def insertString(fb: FilterBypass, offs: Int, str: String, a: AttributeSet){
       if(str.forall((c)=>c.isDigit)) super.insertString(fb, offs, str, a)
    }    
    override def replace(fb: FilterBypass, offs: Int, l: Int, str: String, a: AttributeSet){
       if(str.forall((c)=>c.isDigit)) super.replace(fb, offs, l, str, a)
    }
  }

  peer.getDocument().asInstanceOf[AbstractDocument].setDocumentFilter(IntegralFilter)
}

注意“覆盖”的使用。这就是我得到编译器错误和相应 IDE 提示的方式,如果我真的想用这个覆盖某些东西,我必须更改签名。

于 2012-12-18T06:01:16.827 回答
1

这个类可以正确处理除指数之外的所有有效数字:

class NumberField(initialValue: Double) extends TextField(initialValue.toString) {
  // Note: exponents are not allowed
  val numberFormatException = new NumberFormatException
  listenTo(keys)
  reactions += {
    case event: KeyTyped => {
      try {
        // Don't allow "d" or "f" in the string even though it parses, e.g. 3.5d
        if (event.char.isLetter)
          throw numberFormatException
        // Don't allow string that doesn't parse to a double
        (text.substring(0, caret.position) +
          event.char +
          text.substring(caret.position)).toDouble
      } catch {
        case exception: NumberFormatException => event.consume()
      }
    }
  }

  def value : Double = text.toDouble
}
于 2017-01-19T15:38:13.090 回答