Во-первых, вам нужно иметь четкое представление о scope
и поведении ключевого слова this
в контексте scope
.
this
& amp; scope
:
there are two types of scope in javascript. They are :
1) Global Scope
2) Function Scope
вкратце, глобальная область относится к объекту window.Variables, объявленные в глобальной области, доступны из любого места. С другой стороны, область функций находится внутри функции .variable, объявленный внутри функции, не может быть доступен из внешнего мира в обычном режиме. this
ключевое слово в глобальной области относится к объекту window. Внутренняя функция this
также относится к объекту window.So this
всегда будет ссылаться на окно до тех пор, пока мы найдем способ манипулировать this
, чтобы указать контекст по собственному выбору.
--------------------------------------------------------------------------------
- -
- Global Scope -
- ( globally "this" refers to window object) -
- -
- function outer_function(callback){ -
- -
- // outer function scope -
- // inside outer function"this" keyword refers to window object - -
- callback() // "this" inside callback also refers window object -
- } -
- -
- function callback_function(){ -
- -
- // function to be passed as callback -
- -
- // here "THIS" refers to window object also -
- -
- } -
- -
- outer_function(callback_function) -
- // invoke with callback -
--------------------------------------------------------------------------------
Различные способы управления this
внутри функций обратного вызова:
Здесь У меня есть функция-конструктор, называемая Person. Он имеет свойство, называемое name
, и четыре метода, называемые sayNameVersion1
, sayNameVersion2
, sayNameVersion3
, sayNameVersion4
. Все четыре из них имеют одну конкретную задачу. Заберите обратный вызов и вызовите его. Обратный вызов имеет конкретную задачу, которая заключается в регистрации свойства имени экземпляра функции конструктора Person.
function Person(name){
this.name = name
this.sayNameVersion1 = function(callback){
callback.bind(this)()
}
this.sayNameVersion2 = function(callback){
callback()
}
this.sayNameVersion3 = function(callback){
callback.call(this)
}
this.sayNameVersion4 = function(callback){
callback.apply(this)
}
}
function niceCallback(){
// function to be used as callback
var parentObject = this
console.log(parentObject)
}
Теперь давайте создадим экземпляр из конструктора person и вызывать разные версии sayNameVersionX
(X относится к 1,2,3,4) методу с niceCallback
, чтобы увидеть, как много способов управления this
внутри обратного вызова ссылаться на person
.
var p1 = new Person('zami') // create an instance of Person constructor
Что нужно сделать, это создать новую функцию с ключевым словом this
, установленным на предоставленное значение.
sayNameVersion1
и sayNameVersion2
используют bind для управления this
функции обратного вызова.
this.sayNameVersion1 = function(callback){
callback.bind(this)()
}
this.sayNameVersion2 = function(callback){
callback()
}
сначала связывают this
с обратным вызовом внутри самого метода. для второго обратного вызова передается связанный с ним объект.
p1.sayNameVersion1(niceCallback) // pass simply the callback and bind happens inside the sayNameVersion1 method
p1.sayNameVersion2(niceCallback.bind(p1)) // uses bind before passing callback
first argument
в call
используется как функция this
внутри функции, которая вызывается с call
, прикрепленной к ней.
sayNameVersion3
использует call
для управления this
], чтобы ссылаться на созданный нами объект person, а не на объект окна.
this.sayNameVersion3 = function(callback){
callback.call(this)
}
и он называется следующим:
p1.sayNameVersion3(niceCallback)
Как и в call
, первый аргумент apply
относится к объекту, который будет обозначен ключевым словом this
.
sayNameVersion4
использует apply
для манипулирования this
для обращения к объекту человека
this.sayNameVersion4 = function(callback){
callback.apply(this)
}
, и он называется следующим. Просто передается обратный вызов,
p1.sayNameVersion4(niceCallback)
Простой подход заключается в подклассе JTextField и переопределении createDefaultModel () путем возврата настраиваемого подкласса PlainDocument. Пример - текстовое поле только для целых чисел:
public class NumberField extends JTextField {
@Override
protected Document createDefaultModel() {
return new Numberdocument();
}
class Numberdocument extends PlainDocument
{
String numbers="1234567890-";
@Override
public void insertString(int offs, String str, AttributeSet a)
throws BadLocationException {
if(!numbers.contains(str));
else super.insertString(offs, str, a);
}
}
Способ ввода в insertString () любым способом.
DataTF.addKeyListener(new KeyAdapter() {
@Override
public void keyTyped(KeyEvent eve) {
String AllowedData="0123456789.";
char enter = eve.getKeyChar();
if (!AllowedData.contains(String.valueOf(enter))) {
eve.consume();
}
}
});
Хотя есть чистое зло JFormattedTextField
, нет тривиального способа сделать это, используя только библиотеку Swing.
Некоторый код, который я подготовил ранее. Немного описания.
Быстрое решение:
JTextField textField = new JTextField() {
public void processKeyEvent(KeyEvent ev) {
char c = ev.getKeyChar();
if (c >= 48 && c <= 57) { // c = '0' ... c = '9'
super.processKeyEvent(ev);
}
}
};
Проблема с вышеупомянутым решением заключается в том, что пользователь не может использовать клавиши «Удалить», «Стрелка влево», «Стрелка вправо» или «Назад» в текстовом поле, поэтому я предлагаю использовать это решение:
this.portTextField = new JTextField() {
public void processKeyEvent(KeyEvent ev) {
char c = ev.getKeyChar();
try {
// Ignore all non-printable characters. Just check the printable ones.
if (c > 31 && c < 127) {
Integer.parseInt(c + "");
}
super.processKeyEvent(ev);
}
catch (NumberFormatException nfe) {
// Do nothing. Character inputted is not a number, so ignore it.
}
}
};
Очень простое решение - использовать прослушиватель действий.
TextFieldActionPerformed(java.awt.event.ActionEvent evt) {
try{
Integer.parseInteger(TextField.getText());
}
catch(Exception e){
JOptionPane.showMessageDialog(null, "Please insert Valid Number Only");
TextField.setText(TextField.getText().substring(0,TextField.getText().length()-1));
}
}
Вы можете использовать его и для Double:
Double.parseDouble(TextField.getText());
Этот вопрос был назван «точным дубликатом» другого вопроса, который с тех пор был закрыт. Ответы на этот вопрос были настолько бедными, что я был вдохновлен помочь кому-либо, кто мог бы найти его позже, путем ссылки на гораздо лучший ответ для этого случая использования.
Это ответ на закрытый вопрос & amp; могут быть суммированы как ..
JSpinner
. Попробуйте это в событии с нажатой клавишей для связанного JTextField.
private void JTextField(java.awt.event.KeyEvent evt) {
// TODO add your handling code here:
char enter = evt.getKeyChar();
if(!(Character.isDigit(enter))){
evt.consume();
}
}
записать этот код в введенный ключ
char c=evt.getKeyChar();
if(!(Character.isDigit(c) || (c==KeyEvent.VK_BACK_SPACE || c==KeyEvent.VK_DELETE)))
{
getToolkit().beep();
evt.consume();
}
Вы хотели бы взглянуть на JFormattedTextField
Форматированные текстовые поля предоставляют разработчикам возможность указать допустимый набор символов, которые могут быть напечатано в текстовом поле
blockquote>Это подкласс JTextField, поэтому вы можете использовать его следующим образом:
JTextField textField = new JFormattedTextField(NumberFormat.getInstance());
if (JTextField.getText().equals("") || !(Pattern.matches("^[0-9]+$", JTextField.getText()))) {
JOptionPane.showMessageDialog(null, " JTextField Invalide !!!!! ");
}
import javax.swing.*;
import javax.swing.text.*;
public class JNumberTextField extends JTextField
{
private static final char DOT = '.';
private static final char NEGATIVE = '-';
private static final String BLANK = "";
private static final int DEF_PRECISION = 2;
public static final int NUMERIC = 2;
public static final int DECIMAL = 3;
public static final String FM_NUMERIC = "0123456789";
public static final String FM_DECIMAL = FM_NUMERIC + DOT;
private int maxLength = 0;
private int format = NUMERIC;
private String negativeChars = BLANK;
private String allowedChars = null;
private boolean allowNegative = false;
private int precision = 0;
protected PlainDocument numberFieldFilter;
public JNumberTextField()
{
this( 10, NUMERIC );
}
public JNumberTextField( int maxLen )
{
this( maxLen, NUMERIC );
}
public JNumberTextField( int maxLen, int format )
{
setAllowNegative( true );
setMaxLength( maxLen );
setFormat( format );
numberFieldFilter = new JNumberFieldFilter();
super.setDocument( numberFieldFilter );
}
public void setMaxLength( int maxLen )
{
if (maxLen > 0)
maxLength = maxLen;
else
maxLength = 0;
}
public int getMaxLength()
{
return maxLength;
}
public void setPrecision( int precision )
{
if ( format == NUMERIC )
return;
if ( precision >= 0 )
this.precision = precision;
else
this.precision = DEF_PRECISION;
}
public int getPrecision()
{
return precision;
}
public Number getNumber()
{
Number number = null;
if ( format == NUMERIC )
number = new Integer(getText());
else
number = new Double(getText());
return number;
}
public void setNumber( Number value )
{
setText(String.valueOf(value));
}
public int getInt()
{
return Integer.parseInt( getText() );
}
public void setInt( int value )
{
setText( String.valueOf( value ) );
}
public float getFloat()
{
return ( new Float( getText() ) ).floatValue();
}
public void setFloat(float value)
{
setText( String.valueOf( value ) );
}
public double getDouble()
{
return ( new Double( getText() ) ).doubleValue();
}
public void setDouble(double value)
{
setText( String.valueOf(value) );
}
public int getFormat()
{
return format;
}
public void setFormat(int format)
{
switch ( format )
{
case NUMERIC:
default:
this.format = NUMERIC;
this.precision = 0;
this.allowedChars = FM_NUMERIC;
break;
case DECIMAL:
this.format = DECIMAL;
this.precision = DEF_PRECISION;
this.allowedChars = FM_DECIMAL;
break;
}
}
public void setAllowNegative( boolean value )
{
allowNegative = value;
if ( value )
negativeChars = "" + NEGATIVE;
else
negativeChars = BLANK;
}
public boolean isAllowNegative()
{
return allowNegative;
}
public void setDocument( Document document )
{
}
class JNumberFieldFilter extends PlainDocument
{
public JNumberFieldFilter()
{
super();
}
public void insertString(int offset, String str, AttributeSet attr) throws BadLocationException
{
String text = getText(0,offset) + str + getText(offset,(getLength() - offset));
if ( str == null || text == null )
return;
for ( int i=0; i<str.length(); i++ )
{
if ( ( allowedChars + negativeChars ).indexOf( str.charAt(i) ) == -1)
return;
}
int precisionLength = 0, dotLength = 0, minusLength = 0;
int textLength = text.length();
try
{
if ( format == NUMERIC )
{
if ( ! ( ( text.equals( negativeChars ) ) && ( text.length() == 1) ) )
new Long(text);
}
else if ( format == DECIMAL )
{
if ( ! ( ( text.equals( negativeChars ) ) && ( text.length() == 1) ) )
new Double(text);
int dotIndex = text.indexOf(DOT);
if( dotIndex != -1 )
{
dotLength = 1;
precisionLength = textLength - dotIndex - dotLength;
if( precisionLength > precision )
return;
}
}
}
catch(Exception ex)
{
return;
}
if ( text.startsWith( "" + NEGATIVE ) )
{
if ( !allowNegative )
return;
else
minusLength = 1;
}
if ( maxLength < ( textLength - dotLength - precisionLength - minusLength ) )
return;
super.insertString( offset, str, attr );
}
}
}
Поскольку этот вопрос повторяется довольно часто, я прилагаю к этому больше усилий, чем обычно.
Мое голосование идет к JFormattedTextField
. ИМО каждый разработчик Swing должен иметь улучшенную версию этого класса в своем наборе инструментов, поскольку он позволяет проверять почти все, что вы можете себе представить, правильным выбором Format
. Примеры, для которых я уже использовал его:
String
не может быть пустым JSpinner
Это также позволяет визуальную обратную связь, когда вход недействителен, например, не в случае с InputVerifier
. Он по-прежнему позволяет пользователю вводить что-либо, но это значение просто не принимается, когда оно недействительно, и это значение никогда не покидает пользовательский интерфейс. Я думаю (но опять же, это мое мнение), что лучше разрешить пользователю вводить недопустимый ввод, который просто удаляет это автоматически, например. a DocumentFilter
. Я бы заподозрил ошибку при типе символа в текстовом поле, и он не появляется.
Позвольте мне проиллюстрировать это с помощью некоторого кода (на самом деле, кода). Сначала небольшое демо-приложение. Это приложение просто показывает номер JFormattedTextField
для чисел. Просто использование другого формата позволяет повторно использовать этот компонент для совершенно разных валидаций.
[/g0]
import be.pcl.swing.ImprovedFormattedTextField;
import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.NumberFormat;
/**
* See http://stackoverflow.com/q/1313390/1076463
*/
public class FormattedTextFieldDemo {
public static void main( String[] args ) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JFrame testFrame = new JFrame( "FormattedTextFieldDemo" );
NumberFormat integerNumberInstance = NumberFormat.getIntegerInstance();
ImprovedFormattedTextField integerFormattedTextField = new ImprovedFormattedTextField( integerNumberInstance, 100 );
integerFormattedTextField.setColumns( 20 );
testFrame.add( createButtonPanel( integerFormattedTextField ), BorderLayout.NORTH );
final JTextArea textArea = new JTextArea(50, 50);
PropertyChangeListener updateTextAreaListener = new PropertyChangeListener() {
@Override
public void propertyChange( PropertyChangeEvent evt ) {
textArea.append( "New value: " + evt.getNewValue() + "\n" );
}
};
integerFormattedTextField.addPropertyChangeListener( "value", updateTextAreaListener );
testFrame.add( new JScrollPane( textArea ), BorderLayout.CENTER );
testFrame.setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE );
testFrame.pack();
testFrame.setVisible( true );
}
} );
}
private static JPanel createButtonPanel( final JFormattedTextField aTextField ){
JPanel panel = new JPanel( new BorderLayout( ) );
panel.add( aTextField, BorderLayout.WEST );
Action action = new AbstractAction() {
{
aTextField.addPropertyChangeListener( "editValid", new PropertyChangeListener() {
@Override
public void propertyChange( PropertyChangeEvent evt ) {
setEnabled( ( ( Boolean ) evt.getNewValue() ) );
}
} );
putValue( Action.NAME, "Show current value" );
}
@Override
public void actionPerformed( ActionEvent e ) {
JOptionPane.showMessageDialog( null, "The current value is [" + aTextField.getValue() + "] of class [" + aTextField.getValue().getClass() + "]" );
}
};
panel.add( new JButton( action ), BorderLayout.EAST );
return panel;
}
}
, который показывает только ImprovedFormattedTextField
и JButton
который активируется только тогда, когда вход действителен (ага, есть это решение DocumentFilter
). Он также показывает JTextArea
, в котором значение печатается каждый раз, когда встречается новое действительное значение. Нажатие кнопки показывает значение.
Код для ImprovedFormattedTextField
можно найти ниже, вместе с ParseAllFormat
, на котором он зависит
package be.pcl.swing;
import javax.swing.JFormattedTextField;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.Color;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyEvent;
import java.text.Format;
import java.text.ParseException;
/**
* <p>Extension of {@code JFormattedTextField} which solves some of the usability issues</p>
*/
public class ImprovedFormattedTextField extends JFormattedTextField {
private static final Color ERROR_BACKGROUND_COLOR = new Color( 255, 215, 215 );
private static final Color ERROR_FOREGROUND_COLOR = null;
private Color fBackground, fForeground;
/**
* Create a new {@code ImprovedFormattedTextField} instance which will use {@code aFormat} for the
* validation of the user input.
*
* @param aFormat The format. May not be {@code null}
*/
public ImprovedFormattedTextField( Format aFormat ) {
//use a ParseAllFormat as we do not want to accept user input which is partially valid
super( new ParseAllFormat( aFormat ) );
setFocusLostBehavior( JFormattedTextField.COMMIT_OR_REVERT );
updateBackgroundOnEachUpdate();
//improve the caret behavior
//see also http://tips4java.wordpress.com/2010/02/21/formatted-text-field-tips/
addFocusListener( new MousePositionCorrectorListener() );
}
/**
* Create a new {@code ImprovedFormattedTextField} instance which will use {@code aFormat} for the
* validation of the user input. The field will be initialized with {@code aValue}.
*
* @param aFormat The format. May not be {@code null}
* @param aValue The initial value
*/
public ImprovedFormattedTextField( Format aFormat, Object aValue ) {
this( aFormat );
setValue( aValue );
}
private void updateBackgroundOnEachUpdate() {
getDocument().addDocumentListener( new DocumentListener() {
@Override
public void insertUpdate( DocumentEvent e ) {
updateBackground();
}
@Override
public void removeUpdate( DocumentEvent e ) {
updateBackground();
}
@Override
public void changedUpdate( DocumentEvent e ) {
updateBackground();
}
} );
}
/**
* Update the background color depending on the valid state of the current input. This provides
* visual feedback to the user
*/
private void updateBackground() {
boolean valid = validContent();
if ( ERROR_BACKGROUND_COLOR != null ) {
setBackground( valid ? fBackground : ERROR_BACKGROUND_COLOR );
}
if ( ERROR_FOREGROUND_COLOR != null ) {
setForeground( valid ? fForeground : ERROR_FOREGROUND_COLOR );
}
}
@Override
public void updateUI() {
super.updateUI();
fBackground = getBackground();
fForeground = getForeground();
}
private boolean validContent() {
AbstractFormatter formatter = getFormatter();
if ( formatter != null ) {
try {
formatter.stringToValue( getText() );
return true;
} catch ( ParseException e ) {
return false;
}
}
return true;
}
@Override
public void setValue( Object value ) {
boolean validValue = true;
//before setting the value, parse it by using the format
try {
AbstractFormatter formatter = getFormatter();
if ( formatter != null ) {
formatter.valueToString( value );
}
} catch ( ParseException e ) {
validValue = false;
updateBackground();
}
//only set the value when valid
if ( validValue ) {
int old_caret_position = getCaretPosition();
super.setValue( value );
setCaretPosition( Math.min( old_caret_position, getText().length() ) );
}
}
@Override
protected boolean processKeyBinding( KeyStroke ks, KeyEvent e, int condition, boolean pressed ) {
//do not let the formatted text field consume the enters. This allows to trigger an OK button by
//pressing enter from within the formatted text field
if ( validContent() ) {
return super.processKeyBinding( ks, e,
condition, pressed ) && ks != KeyStroke.getKeyStroke( KeyEvent.VK_ENTER, 0 );
}
else {
return super.processKeyBinding( ks, e,
condition, pressed );
}
}
private static class MousePositionCorrectorListener extends FocusAdapter {
@Override
public void focusGained( FocusEvent e ) {
/* After a formatted text field gains focus, it replaces its text with its
* current value, formatted appropriately of course. It does this after
* any focus listeners are notified. We want to make sure that the caret
* is placed in the correct position rather than the dumb default that is
* before the 1st character ! */
final JTextField field = ( JTextField ) e.getSource();
final int dot = field.getCaret().getDot();
final int mark = field.getCaret().getMark();
if ( field.isEnabled() && field.isEditable() ) {
SwingUtilities.invokeLater( new Runnable() {
@Override
public void run() {
// Only set the caret if the textfield hasn't got a selection on it
if ( dot == mark ) {
field.getCaret().setDot( dot );
}
}
} );
}
}
}
}
. ParseAllFormat
class:
package be.pcl.swing;
import java.text.AttributedCharacterIterator;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParseException;
import java.text.ParsePosition;
/**
* <p>Decorator for a {@link Format Format} which only accepts values which can be completely parsed
* by the delegate format. If the value can only be partially parsed, the decorator will refuse to
* parse the value.</p>
*/
public class ParseAllFormat extends Format {
private final Format fDelegate;
/**
* Decorate <code>aDelegate</code> to make sure if parser everything or nothing
*
* @param aDelegate The delegate format
*/
public ParseAllFormat( Format aDelegate ) {
fDelegate = aDelegate;
}
@Override
public StringBuffer format( Object obj, StringBuffer toAppendTo, FieldPosition pos ) {
return fDelegate.format( obj, toAppendTo, pos );
}
@Override
public AttributedCharacterIterator formatToCharacterIterator( Object obj ) {
return fDelegate.formatToCharacterIterator( obj );
}
@Override
public Object parseObject( String source, ParsePosition pos ) {
int initialIndex = pos.getIndex();
Object result = fDelegate.parseObject( source, pos );
if ( result != null && pos.getIndex() < source.length() ) {
int errorIndex = pos.getIndex();
pos.setIndex( initialIndex );
pos.setErrorIndex( errorIndex );
return null;
}
return result;
}
@Override
public Object parseObject( String source ) throws ParseException {
//no need to delegate the call, super will call the parseObject( source, pos ) method
return super.parseObject( source );
}
}
Возможные улучшения:
setBackground
не соблюдается всеми Look-and-Feels. Иногда вы можете использовать setForeground
вместо этого, но даже это не гарантируется всеми L & amp; Fs. Поэтому для визуальной обратной связи может быть лучше использовать восклицательный знак, расположенный рядом с полем. Недостатком является то, что это может испортить макет, если вы вдруг добавите / удалите значок Format
, которое включает описание / пример допустимого ввода, и поместите его в качестве подсказки на JFormattedTextField
. JFormattedTextField
использовать только алфавиты переменной длины?
– Akshat
1 April 2015 в 16:06
java.util.format
, о которой вы можете думать
– Robin
1 April 2015 в 16:39
Вы можете создать красивое текстовое поле в java, которое принимает или разрешает только числовые значения. Вы даже можете установить точность для значений float ... проверьте код в zybocodes
numberField = new JFormattedTextField (NumberFormat.getInstance ());
Я думаю, что это лучшее решение:
JTextField textField = new JFormattedTextField(new MaskFormatter("###")); //
Рассматривая количество просмотров, которые этот вопрос получает, я не нашел ни одного из вышеупомянутых решений, подходящих для моей проблемы. Я решил создать пользовательский PlainDocument , чтобы он соответствовал моим потребностям. Это решение также подает звуковой сигнал при достижении максимального количества символов, или вставленный текст не является целым числом.
private class FixedSizeNumberDocument extends PlainDocument
{
private JTextComponent owner;
private int fixedSize;
public FixedSizeNumberDocument(JTextComponent owner, int fixedSize)
{
this.owner = owner;
this.fixedSize = fixedSize;
}
@Override
public void insertString(int offs, String str, AttributeSet a)
throws BadLocationException
{
if (getLength() + str.length() > fixedSize) {
str = str.substring(0, fixedSize - getLength());
this.owner.getToolkit().beep();
}
try {
Integer.parseInt(str);
} catch (NumberFormatException e) {
// inserted text is not a number
this.owner.getToolkit().beep();
return;
}
super.insertString(offs, str, a);
}
}
имплантируется следующим образом:
JTextField textfield = new JTextField();
textfield.setDocument(new FixedSizeNumberDocument(textfield,5));
Также рассмотрите использование InputVerifier
.
Используйте formatter
для форматирования текстового поля.
NumberFormat format = NumberFormat.getInstance();
format.setGroupingUsed(false);
NumberFormatter formatter = new NumberFormatter(format);
formatter.setValueClass(Integer.class);
formatter.setMaximum(65535);
formatter.setAllowsInvalid(false);
formatter.setCommitsOnValidEdit(true);
myTextField = new JFormattedTextField(formatter);