Сделать JFormattedTextField вести себя как вход ATM

44
3

Я хотел бы знать, есть ли способ заставить JformattedTextField или jtextField вести себя как входные деньги atm. С этим я подразумеваю, что вы входите справа налево, говорите, что вы входите в 10, вам нужно нажать еще 2, чтобы оно было 10.00. Программа автоматически вводит десятичную точку, когда он набирает справа налево? Если 2 0 не введены, это будет только.10. Это возможно? Как это будет возвращено мне, если я захочу использовать эту строку для выполнения вычислений? Я попробовал абстрактный форматтер, но это не работает так хорошо. Я хочу использовать это для ввода суммы денег, полученной клиентом. Но сделайте это идиотом.

спросил(а) 2013-06-12T23:29:00+04:00 6 лет, 6 месяцев назад
3
Решение
70

Это заставляет пользователя всегда вводить текст справа, независимо от того, где находится каретка. Все предыдущие символы сдвигаются влево при вводе нового символа. Форматирование будет применяться на основе вашего форматирования:

import java.awt.*;
import java.text.*;
import javax.swing.*;
import javax.swing.text.*;

public class ABMTextField extends JTextField
{
private DecimalFormat format;
private String decimal;

public ABMTextField(DecimalFormat format)
{
this.format = format;

decimal = Character.toString( format.getDecimalFormatSymbols().getDecimalSeparator() );

setColumns( format.toPattern().length() );
setHorizontalAlignment(JFormattedTextField.TRAILING);

setText( format.format(0.0) );

AbstractDocument doc = (AbstractDocument)getDocument();
doc.setDocumentFilter( new ABMFilter() );
}

@Override
public void setText(String text)
{
Number number = format.parse(text, new ParsePosition(0));

if (number != null)
super.setText( text );
}

public class ABMFilter extends DocumentFilter
{
public void insertString(FilterBypass fb, int offs, String str, AttributeSet a)
throws BadLocationException
{
replace(fb, offs, 0, str, a);
}

public void replace(FilterBypass fb, int offs, int length, String str, AttributeSet a)
throws BadLocationException
{
if ("0123456789".contains(str))
{
Document doc = fb.getDocument();
StringBuilder sb = new StringBuilder( doc.getText(0, doc.getLength()) );

int decimalOffset = sb.indexOf( decimal );

if (decimalOffset != -1)
{
sb.deleteCharAt(decimalOffset);
sb.insert(decimalOffset + 1, decimal);
}

sb.append(str);

try
{
String text = format.format( format.parse( sb.toString() ) );
super.replace(fb, 0, doc.getLength(), text, a);
}
catch(ParseException e) {}
}
else
Toolkit.getDefaultToolkit().beep();
}

public void remove(DocumentFilter.FilterBypass fb, int offset, int length)
throws BadLocationException
{
Document doc = fb.getDocument();
StringBuilder sb = new StringBuilder( doc.getText(0, doc.getLength()) );

int decimalOffset = sb.indexOf( decimal );

if (decimalOffset != -1)
{
sb.deleteCharAt(decimalOffset);
sb.insert(decimalOffset - 1, decimal);
}

sb.deleteCharAt( sb.length() - 1) ;

try
{
String text = format.format( format.parse( sb.toString() ) );
super.replace(fb, 0, doc.getLength(), text, null);
}
catch(ParseException e) {}
}
}

private static void createAndShowUI()
{
DecimalFormat format = new DecimalFormat("###,##0.00");
ABMTextField abm = new ABMTextField( format );

JPanel panel = new JPanel();
panel.add( abm );

JFrame frame = new JFrame("ABMTextField");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( panel );
frame.setSize(200, 200);
frame.setLocationByPlatform( true );
frame.setVisible( true );
}

public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}

Как это будет возвращено мне, если я захочу использовать эту строку для выполнения вычислений?

Вам нужно будет создать метод, возможно getValue(), который будет использовать метод format.parse(...) для возврата фактического числа.

ответил(а) 2013-06-13T04:52:00+04:00 6 лет, 5 месяцев назад
Еще 2 ответа
55

Посмотрите, как использовать форматированные текстовые поля, в частности, с помощью MaskFormatter.

Что-то вроде...

MaskFormatter formatter = new MaskFormatter("##.##");
JFormattedTextField field = JFormattedTextField(formatter);

например, может помочь.

Простой пример

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.HeadlessException;
import java.text.ParseException;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.text.DefaultFormatterFactory;
import javax.swing.text.MaskFormatter;

public class TestFormattedTextField {

public static void main(String[] args) {
new TestFormattedTextField();
}

public TestFormattedTextField() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}

try {
JFormattedTextField field = new JFormattedTextField();
MaskFormatter formatter = new MaskFormatter("##.##");
formatter.setPlaceholderCharacter('0');
field.setFormatterFactory(new DefaultFormatterFactory(formatter));

JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
frame.add(field);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (ParseException exp) {
exp.printStackTrace();
}
}
});
}
}

Дополнительный пример

Теперь я понимаю, что предыдущий пример не соответствует вашим конкретным потребностям (как вы их описали), это простое решение, я также добавил пример DocumentFilter...

enter image description here


Что будет выводить...

Value = 0.1
Value = $0.10

enter image description here

Что будет выводить

Value = 10.0
Value = $10.00

Код...

import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.NumberFormat;
import java.text.ParseException;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import javax.swing.text.MaskFormatter;

public class TestFormattedTextField {

public static void main(String[] args) {
new TestFormattedTextField();
}

public TestFormattedTextField() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}

MoneyField field = new MoneyField();
field.addActionListener(new ActionListener() {
@Override
@SuppressWarnings("empty-statement")
public void actionPerformed(ActionEvent e) {
MoneyField field = (MoneyField) e.getSource();
double value = field.getValue();
System.out.println("Value = " + value);
System.out.println("Value = " + NumberFormat.getCurrencyInstance().format(value));
}
});

JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
frame.add(field);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}

public class MoneyField extends JTextField {

public MoneyField() {
setColumns(5);
setHorizontalAlignment(RIGHT);
((AbstractDocument) getDocument()).setDocumentFilter(new Filter());
}

public double getValue() {

String text = getText();
if (!text.contains(".")) {
text = "0." + text;
}

return Double.parseDouble(text);

}

protected class Filter extends DocumentFilter {

protected String getNumbers(String text) {
StringBuilder sb = new StringBuilder(text.length());
for (char c : text.toCharArray()) {
if (Character.isDigit(c)) {
sb.append(c);
}
}
return sb.toString();
}

@Override
public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
if (length > 0) {
fb.remove(offset, length);
}
insertString(fb, offset, text, attrs);
}

@Override
public void insertString(FilterBypass fb, int offset, String text, AttributeSet attr) throws BadLocationException {
text = getNumbers(text);
if (text.length() > 0) {
int docLength = fb.getDocument().getLength();
if (docLength == 2) {
text = "." + text;
}
if (docLength + text.length() < 6) {
super.insertString(fb, offset, text, attr);
}
}
}

@Override
public void remove(FilterBypass fb, int offset, int length) throws BadLocationException {
if (offset == 3) {
offset = 2;
length = 2;
}
super.remove(fb, offset, length);
}
}
}
}

Ознакомьтесь с примерами DocumentFilter для получения более подробной информации.

ответил(а) 2013-06-13T01:20:00+04:00 6 лет, 6 месяцев назад
48

Используйте DocumentFilter для JTextField и переопределите соответствующий метод для обработки форматирования чисел. Также будет хорошо, если вы сможете опубликовать то, что вы пробовали, и "не работает".

ответил(а) 2013-06-13T01:51:00+04:00 6 лет, 5 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема