【问题标题】:Solution for Numeric Text Field in GWTGWT中数字文本字段的解决方案
【发布时间】:2010-05-19 12:57:57
【问题描述】:

我需要一个与 Gxt 的 NumberField 行为非常相似的文本字段。不幸的是,我没有在我的应用程序中使用 Gxt,而且 GWT 2.0 还没有数字文本字段实现。

因此,目前我可以选择通过使用键盘处理程序过滤掉非数字击键来模拟 NumberField。

这是解决问题的最佳方法吗?这里有人有更好的解决方案/方法吗?

提前致谢:)

【问题讨论】:

  • 猜猜,这是 CRUD 应用程序中非常频繁的要求。想知道你们是如何实现它的。
  • 通过Key*Handlers 之一进行过滤似乎非常简单——您还需要/期待什么?您还可以查看 GXT 的源代码,了解他们是如何实现 NumberField 的——在 GWT 中重新实现它应该是轻而易举的事。

标签: gwt gwt2


【解决方案1】:

在这里您可以找到我在我的一个课程中使用的代码。这些功能比 GXT 的功能要有限得多,但应该让您走上正确的轨道。

这是一个非常基本的小部件,但可以满足我的需要。

public class ValueTextBox extends TextBox {

    private int min = 0;
    private int max = 100;
    private boolean minConstrained = true;
    private boolean maxConstrained = true;
    private int minDigits = 1;
    private int step = 1;

    private KeyUpHandler keyUpHandler = new KeyUpHandler() {

        @Override
        public void onKeyUp(KeyUpEvent event) {
            if (isReadOnly() || !isEnabled()) {
                return;
            }

            int keyCode = event.getNativeEvent().getKeyCode();

            boolean processed = false;

            switch (keyCode) {
            case KeyCodes.KEY_LEFT:
            case KeyCodes.KEY_RIGHT:
            case KeyCodes.KEY_BACKSPACE:
            case KeyCodes.KEY_DELETE:
            case KeyCodes.KEY_TAB:
                if (getText().isEmpty()) {
                    setValue(formatValue(min));
                }
                return;
            case KeyCodes.KEY_UP:
                if (step != 0) {
                    increaseValue();
                    processed = true;
                }
                break;
            case KeyCodes.KEY_DOWN:
                if (step != 0) {
                    decreaseValue();
                    processed = true;
                }
                break;
            }

            if (processed) {
                cancelKey();
            }
        }

    };

    private KeyPressHandler keyPressHandler = new KeyPressHandler() {
        @Override
        public void onKeyPress(KeyPressEvent event) {

            if (isReadOnly() || !isEnabled()) {
                return;
            }

            int keyCode = event.getNativeEvent().getKeyCode();

            switch (keyCode) {
            case KeyCodes.KEY_LEFT:
            case KeyCodes.KEY_RIGHT:
            case KeyCodes.KEY_BACKSPACE:
            case KeyCodes.KEY_DELETE:
            case KeyCodes.KEY_TAB:
            case KeyCodes.KEY_UP:
            case KeyCodes.KEY_DOWN:
                return;
            }

            int index = getCursorPos();
            String previousText = getText();
            String newText;
            if (getSelectionLength() > 0) {
                newText = previousText.substring(0, getCursorPos())
                        + event.getCharCode()
                        + previousText.substring(getCursorPos()
                                + getSelectionLength(), previousText.length());
            } else {
                newText = previousText.substring(0, index)
                        + event.getCharCode()
                        + previousText.substring(index, previousText.length());
            }
            cancelKey();

            setValue(newText, true);
        }
    };

    public ValueTextBox(int value) {
        this(value, 0, 100);
    }

    public ValueTextBox(int value, int min, int max) {
        this(value, min, max, true);
    }

    public ValueTextBox(int value, int min, int max, boolean constrained) {
        this(value, min, max, constrained, constrained);
    }

    public ValueTextBox(int value, int min, int max, boolean minConstrained,
            boolean maxConstrained) {
        super();

        addKeyPressHandler(keyPressHandler);
        addKeyUpHandler(keyUpHandler);

        this.min = min;
        this.max = max;
        this.minConstrained = minConstrained;
        this.maxConstrained = maxConstrained;

        setValue(formatValue(value), false);
        setTextAlignment(TextBoxBase.ALIGN_CENTER);
        setStyleName(Resources.INSTANCE.css().fwFormEntry());
    }

    public void setMinDigits(int minDigits) {
        if (minDigits > 0) {
            this.minDigits = minDigits;

            String value = getText();
            long newValue = parseValue(value);

            setText(formatValue(newValue));
        }
    }

    public void setSteps(int step) {
        this.step = step;
    }

    protected void increaseValue() {
        if (step != 0) {
            String value = getText();
            long newValue = parseValue(value);
            newValue += step;
            if (maxConstrained && (newValue > max)) {
                return;
            }
            setValue(formatValue(newValue));
        }
    }

    protected void decreaseValue() {
        if (step != 0) {
            String value = getText();
            long newValue = parseValue(value);
            newValue -= step;
            if (minConstrained && (newValue < min)) {
                return;
            }
            setValue(formatValue(newValue));
        }
    }

    /**
     * @param value
     *            the value to format
     * @return the formatted value
     */
    protected String formatValue(long value) {
        String newValue = String.valueOf(value);

        if (minDigits > newValue.length()) {
            String leading = StringUtils.repeat("0", (minDigits - newValue
                    .length()));
            newValue = leading + newValue;
        }

        return newValue;
    }

    @Override
    public void setValue(String value) {
        setValue(value, false);
    }

    @Override
    public void setValue(String value, boolean fireEvents) {
        try {
            long newValue = parseValue(value);
            if ((maxConstrained && (newValue > max))
                    || (minConstrained && (newValue < min))) {
                return;
            }
            String prevText = getValue();
            super.setText(formatValue(newValue));
            if (fireEvents) {
                ValueChangeEvent.fireIfNotEqual(this, getValue(), prevText);
            }
        } catch (Exception ex) {
            // Do Nothing
            System.out.println(ex.getMessage());
        }
    }

    /**
     * @param value
     *            the value to parse
     * @return the parsed value
     */
    protected long parseValue(String value) {
        return Long.valueOf(value);
    }
}

更新:代码在https://github.com/ctasada/GWT-Eureka

【讨论】:

  • 感谢 Carlos,我已经完全在 KeyPressHandler 中按照类似的方式在 NumberField 上实现了我的版本,因为我不需要 keyUp 和 KeyDown - 类似微调器的功能。我特别喜欢你的 formatValue 技术,因为它也巧妙地传达了该领域的最大限制——计划借用你的想法;)我一到我的开发工作站就会发布我的版本。谢谢:)
  • 这很有帮助——我可以在商业上使用该代码吗?如果是,在什么条件下?
  • @slartidan。如果对您有帮助,请投票;)如果您需要额外帮助,请与我联系。
【解决方案2】:

这是一个简单的 KeyPressHandler 允许用户输入十进制数字;

public void onKeyPress(KeyPressEvent event){
    TextBox sender = (TextBox)event.getSource();

    if (sender.isReadOnly() || !sender.isEnabled()) {
        return;
    }

    Character charCode = event.getCharCode();
    int unicodeCharCode = event.getUnicodeCharCode();

    // allow digits, '.' and non-characters
    if (!(Character.isDigit(charCode) || charCode == '.' || unicodeCharCode == 0)){
        sender.cancelKey();
    }
}

【讨论】:

  • 此解决方案允许多个小数点,这会产生无效的小数点数。
【解决方案3】:

不知道这些类是什么时候添加到 GWT 中的,但它们对我来说可以正常工作,无需任何额外代码:

com.google.gwt.user.client.ui.DoubleBox
com.google.gwt.user.client.ui.IntegerBox
com.google.gwt.user.client.ui.LongBox 

对于更高级的验证,您可能希望使用一些自定义解析器覆盖其基类 ValueBox...

【讨论】:

    【解决方案4】:

    这是我对 NumberField 的实现。功能与 Carlos 的版本非常相似,但额外支持十进制输入和非数字键过滤。

    public class NumberBox extends TextBox
    {
    private boolean isDecimal = false;
    
    public NumberBox( )
    {
    }
    
    public boolean isDecimal( )
    {
        return isDecimal;
    }
    
    public void setDecimal( boolean isDecimal )
    {
        this.isDecimal = isDecimal;
    }
    
    public Integer getIntegerValue( )
    {
        return ( StringUtil.isEmpty( getSanitizedValue( ) ) ) ? null : Integer.parseInt( getSanitizedValue( ) );
    }
    
    @Override
    protected void initialize( )
    {
        super.initialize( );
        addStyleName( "number" );
    
        this.addKeyPressHandler( new KeyPressHandler( )
        {
            public void onKeyPress( KeyPressEvent event )
            {
                if ( !isEnabled( ) || isReadOnly( ) )
                    return;
    
                int keyCode = event.getNativeEvent( ).getKeyCode( );
    
                // allow special keys
                if ( ( keyCode == KeyCodes.KEY_BACKSPACE )
                        || ( keyCode == KeyCodes.KEY_DELETE )
                        || ( keyCode == KeyCodes.KEY_ENTER ) || ( keyCode == KeyCodes.KEY_ESCAPE ) || ( keyCode == KeyCodes.KEY_RIGHT )
                        || ( keyCode == KeyCodes.KEY_LEFT ) || ( keyCode == KeyCodes.KEY_TAB ) )
                    return;
    
                // check for decimal '.'
                if ( isDecimal( ) && '.' == (char)keyCode && !getValue( ).contains( "." ) )
                    return;
    
                // filter out non-digits
                if ( Character.isDigit( charCode ) )
                    return;
    
                cancelKey( );
            }
        } );
    }
    

    }


    PS:超类 TextBox 是一个自定义类,它扩展了 GWT TextBox 并具有一些额外的应用程序特定功能。方法 initialize() 基本上是在 TextBox 构造函数中调用的,而 getSanitizedValue 会通过修剪进行一些基本的健全性检查。

    【讨论】:

      【解决方案5】:

      Carlos Tasada 答案有效,但包含一个错误:您应该在 switch/case 块之前添加 event.isShiftKeyDown() 检查 onKeyPress 处理程序。否则它将传递一些符号,如'('。

      【讨论】:

      • 但还是会通过 ' 和 .符号,因此您还需要检查 event.getCharCode()
      【解决方案6】:

      根据 Julian Downes 的回答,您可以这样做:

      text.addKeyPressHandler(new KeyPressHandler() {
      
              @Override
              public void onKeyPress(KeyPressEvent event) {
                  TextBox sender = (TextBox) event.getSource();
      
                  if (sender.isReadOnly() || !sender.isEnabled()) {
                      return;
                  }
                  if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER){
                      return;
                  }
      
                  Character charCode = event.getCharCode();
      
                  try{
                      Double.parseDouble(sender.getText().concat(charCode.toString()));
                  }
                  catch(Exception e){
                      sender.cancelKey();
                  }
              }
          });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-09-28
        • 2020-05-14
        • 2022-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多