Advanced Formatted Text Field Input Manipulation

advanced formatted text field input manipulation?

Solve one problem at a time. Start with an working example. Change it to handle multiple fields, as shown below. Finding the average is now a simple change to update().

image

import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JPanel;

/**
* @see https://stackoverflow.com/q/8703464/230513
* @see https://stackoverflow.com/questions/6803976
*/
public class Adder extends JPanel {

private static final int MAX = 3;
private final List<JFormattedTextField> fields =
new ArrayList<JFormattedTextField>();
private final NumberFormat format = NumberFormat.getNumberInstance();
private final JFormattedTextField sum = new JFormattedTextField(format);

public Adder() {
this.setLayout(new GridLayout(0, 1));
for (int i = 0; i < MAX; i++) {
JFormattedTextField tf = init();
fields.add(tf);
this.add(tf);
}
sum.setHorizontalAlignment(JFormattedTextField.RIGHT);
sum.setEditable(false);
sum.setFocusable(false);
this.add(sum);
}

private JFormattedTextField init() {
JFormattedTextField jtf = new JFormattedTextField(format);
jtf.setValue(0);
jtf.setHorizontalAlignment(JFormattedTextField.RIGHT);
jtf.addFocusListener(new FocusAdapter() {

@Override
public void focusLost(FocusEvent e) {
EventQueue.invokeLater(new Runnable() {

@Override
public void run() {
update();
}
});
}
});
jtf.addPropertyChangeListener("value", new PropertyChangeListener() {

@Override
public void propertyChange(PropertyChangeEvent e) {
update();
}
});
return jtf;
}

private void update() {
long total = 0;
for (JFormattedTextField tf : fields) {
Number v = (Number) tf.getValue();
total += v.longValue();
}
sum.setValue(total);
}

private void display() {
JFrame f = new JFrame("Adder");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}

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

@Override
public void run() {
new Adder().display();
}
});
}
}

java swing get all editable jformattedtextfields and calculate?

add DocumentListener to all JFormattedTextFields and take value from Number instance, for eample for Float

if (someTextField.isEditable()){ 
float newValue = (((Number) resistorValue.getValue()).floatValue());
}

How to Auto Calculate input numeric values of Text Field in JAVA

I suggest use a DocumentFilter this will allow us to kill 2 birds with 1 stone.

1) we need to filter what is inputted to JTextFields to make sure our calculation wont go wrong

2) We need to update the total on the fly i.e as more digits are added/removed.

Here is an example I made which uses DocumentFilter and as you will see the Total field will be updated each time a new digit is entered/added to the JTextField(s) (also it wont allow alphabetic characters etc only digits):

Sample Image

import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import javax.swing.text.DocumentFilter.FilterBypass;

public class DocumentFilterOnTheFlyCalculation {

public DocumentFilterOnTheFlyCalculation() {
createAndShowGui();
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new DocumentFilterOnTheFlyCalculation();
}
});
}

private void createAndShowGui() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridLayout(4, 2));

JLabel label1 = new JLabel("Add:");
final JTextField jtf1 = new JTextField();

JLabel label2 = new JLabel("Add:");
final JTextField jtf2 = new JTextField();

JLabel label3 = new JLabel("Subtract:");
final JTextField jtf3 = new JTextField();

JLabel totalLabel = new JLabel("Total:");
final JTextField totalField = new JTextField("0");
totalField.setEditable(false);

DocumentFilter df = new DocumentFilter() {
@Override
public void insertString(FilterBypass fb, int i, String string, AttributeSet as) throws BadLocationException {

if (isDigit(string)) {
super.insertString(fb, i, string, as);
calcAndSetTotal();
}
}

@Override
public void remove(FilterBypass fb, int i, int i1) throws BadLocationException {
super.remove(fb, i, i1);
calcAndSetTotal();
}

@Override
public void replace(FilterBypass fb, int i, int i1, String string, AttributeSet as) throws BadLocationException {
if (isDigit(string)) {
super.replace(fb, i, i1, string, as);
calcAndSetTotal();

}
}

private boolean isDigit(String string) {
for (int n = 0; n < string.length(); n++) {
char c = string.charAt(n);//get a single character of the string
//System.out.println(c);
if (!Character.isDigit(c)) {//if its an alphabetic character or white space
return false;
}
}
return true;
}

void calcAndSetTotal() {
int sum = 0;

if (!jtf1.getText().isEmpty()) {
sum += Integer.parseInt(jtf1.getText());//we must add this
}
if (!jtf2.getText().isEmpty()) {
sum += Integer.parseInt(jtf2.getText());//we must add this
}
if (!jtf3.getText().isEmpty()) {
sum -= Integer.parseInt(jtf3.getText());//we must subtract this
}

totalField.setText(String.valueOf(sum));
}
};

((AbstractDocument) (jtf1.getDocument())).setDocumentFilter(df);
((AbstractDocument) (jtf2.getDocument())).setDocumentFilter(df);
((AbstractDocument) (jtf3.getDocument())).setDocumentFilter(df);

frame.add(label1);
frame.add(jtf1);
frame.add(label2);
frame.add(jtf2);
frame.add(label3);
frame.add(jtf3);
frame.add(totalLabel);
frame.add(totalField);

frame.pack();
frame.setVisible(true);
}
}

Updating the sum of jTextFields automatically everytime they change (Java)

As @Reimeus suggested, you need to add Document Listener to each of your text fields. Since you're performing the addition in your jButton1ActionPerformed() method, I made the notification of the listeners call this method whenever there's a change to your text fields.

Note: Based on the comments, I've updated my code to include only one DocumentListener and also added a DocumentFilter to accept only numeric input. I also removed the button that was present in the original code to perform the summation

Here's your updated code:

import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;

public class Frame extends javax.swing.JFrame {

public Frame() {
initComponents();
}

@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {

n1 = new javax.swing.JTextField();
n2 = new javax.swing.JTextField();
n3 = new javax.swing.JTextField();
sum = new javax.swing.JTextField();
jLabel1 = new javax.swing.JLabel();
jLabel2 = new javax.swing.JLabel();
jLabel3 = new javax.swing.JLabel();
jLabel5 = new javax.swing.JLabel();

DocumentListener documentListener = new DocumentListener() {

@Override
public void removeUpdate(DocumentEvent e) {
performSummation(null);
}

@Override
public void insertUpdate(DocumentEvent e) {
performSummation(null);
}

@Override
public void changedUpdate(DocumentEvent e) {
}
};

DocumentFilter numericFilter = new DocumentFilter(){

@Override
public void insertString(FilterBypass fb, int offset,
String string, AttributeSet attr)
throws BadLocationException {
fb.insertString(offset, string.replaceAll("[^\\d]", ""), attr);
}

@Override
public void replace(FilterBypass fb, int offset, int length,
String text, AttributeSet attrs)
throws BadLocationException {

fb.replace(offset, length, text.replaceAll("[^\\d]", ""), attrs);
}
};

((AbstractDocument) n1.getDocument()).setDocumentFilter(numericFilter);
((AbstractDocument) n2.getDocument()).setDocumentFilter(numericFilter);
((AbstractDocument) n3.getDocument()).setDocumentFilter(numericFilter);

n1.getDocument().addDocumentListener(documentListener);
n2.getDocument().addDocumentListener(documentListener);
n3.getDocument().addDocumentListener(documentListener);

setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

jLabel1.setText("n1");
jLabel2.setText("n2");
jLabel3.setText("n3");
jLabel5.setText("result");

javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(15, 15, 15)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jLabel1)
.addComponent(jLabel2)
.addComponent(jLabel3)))
.addGroup(layout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jLabel5)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(sum, javax.swing.GroupLayout.PREFERRED_SIZE, 59, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(30, 30, 30)
.addContainerGap())
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(n1, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(n2, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(n3, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(0, 0, Short.MAX_VALUE))))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(32, 32, 32)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(n1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel1))
.addGap(10, 10, 10)
.addComponent(n2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(jLabel2))
.addGap(20, 20, 20)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(n3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel3))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(sum, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel5))
.addContainerGap(38, Short.MAX_VALUE))
);

pack();
}// </editor-fold>

private void performSummation(java.awt.event.ActionEvent evt) {
int total = 0;
if(n1.getText().trim().length() > 0){
try{
total += Integer.parseInt(n1.getText());
}catch(NumberFormatException nbx){
}
}

if(n2.getText().trim().length() > 0){
try{
total += Integer.parseInt(n2.getText());
}catch(NumberFormatException nbx){
}
}

if(n3.getText().trim().length() > 0){
try{
total += Integer.parseInt(n3.getText());
}catch(NumberFormatException nbx){
}
}

sum.setText(""+total);

}

public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(Frame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(Frame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(Frame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(Frame.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>

/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new Frame().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel5;
private javax.swing.JTextField n1;
private javax.swing.JTextField n2;
private javax.swing.JTextField n3;
private javax.swing.JTextField sum;
// End of variables declaration
}

A couple of pointers:

  • Never trust the input that comes from the user. There's a possibility that the user might enter an incorrect value (say something that is not an Integer). As such it is always a good idea to validate your input and check whether the input can be actually parsed. Keeping this in mind, I'ved updated your jButton1ActionPerformed() method

  • The other alternative is to use a Formatted Text Fields

Retrieve integer from JTextfields and apply them to a sum

What you're doing is concatenating two Strings first and then parsing the resulting String -- not what you want. What you want to do is to parse the text individually before adding them together.

try {
int appleInt = Integer.parseInt(apple.getText());
int pearInt = Integer.parseInt(pear.getText());

int result = appleInt + pearInt;

// do something with result

} catch (NumberFormatException nfe) {
// warn user that text is wrong
// clear text fields
}

Modifying text inside textChange nativescript

There is a better way to do what you're doing, but I'm not sure if there's an even better way. Coming from iOS development, I know there is definitely a more appropriate place to do this sort of manipulation, but doing it here shouldn't be causing you to reach the max stack.

If you update your source to do this instead, you will avoid the maximum stack limit (and significantly increase performance of your app). It is not the best way, but it is the best way that I have found available in NativeScript at this time.

@HostListener("textChange")
public onTextChange(target): void {
let newText: string = this.phoneFormatPipe.transform(this.el.text);
if (this.el.text !== newText) {
this.el.text = newText;
}
}

Converting an input field into a Rich Text Editor

You can try Jodit editor. Its open source and can be used on textarea.

This is the examples link:- https://froala.com/wysiwyg-editor/examples/textarea/

This is the documentation link :- https://xdsoft.net/jodit/doc/

HTML Form Field - How to require an input format

The easiest way to do that is by simply using multiple fields:

<div>
Phone:
(<input type="text" name="phone-1" maxlength="3">)
<input type="text" name="phone-2" maxlength="3">-
<input type="text" name="phone-3" maxlength="4">
</div>
<div>
SSN:
<input type="text" name="ssn-1">-
<input type="text" name="ssn-2">-
<input type="text" name="ssn-3">
</div>

While this approach is certainly easy, it's not great. The user has to press tab or click on each field to enter the data, and there's nothing (other than common sense) from preventing them from entering things other than digits.

I always feel that, when it comes to validation, the less you can get in the user's way, the better. Let them enter their phone number in whatever format they like, then you scrub it, removing everything but digits. That way the user can enter "5555551212" or "(555) 555-1212", but the database will always hold "5555551212".

The other thing to consider is that HTML5 offers some nice specific types for phone numbers (but not SSNs). A modern browser will take care of all the input validation and, even better, mobile devices will show the numeric keypad instead of the whole keypad.

Given that, the best way to display your form is this:

<div>
<label for="fieldPhone">Phone: </label>
<input type="tel" id="fieldPhone" placeholder="(555) 555-1212">
</div>
<div>
<label for="fieldSsn">SSN: </label>
<input type="text" id="fieldSsn" name="ssn" placeholder="555-55-5555" pattern="\d{3}-?\d{2}-?\d{4}">
</div>

If the user has a modern browser, this will handle the user side of the input validation for you. If they don't, you'll have to use a validation library or polyfill. There's a whole list of HTMl5 form validation polyfills here:

https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills#wiki-web-forms

So all that remains is now to normalize your data when you save it to the database.

The ideal place to do that would be the back end; it doesn't say where your form is going, though, so maybe you don't have any say on how things are processed on the back end. So you can do this in the front end instead. For example, using jQuery:

$('form').on('submit', function(){
$(this).find('input[type="tel"]').each(function(){
$(this).val() = $(this).val().replace(/[\s().+-]/g, '');
});
$(this).find('input[name="ssn"]').each(function(){
$(this).val() = $(this).val().replace(/-/g, '');
});
});

This is not a perfect approach either: if you do validation in this function, and the validation fails, the user will see his or her input replaced by the normalized versions, which can be disconcerting.

The best approach would be to use AJAX and .serialize; not only can you have better control over the UI, but you can do all the validation you want. But that's probably a little beyond what you need to do right now.

Note that phone validation is the trickiest. The HTML5 phone validation is very permissive, allowing people to enter international phone numbers, which can have pretty complicated formats. Even people in the US will sometimes enter phone numbers like "+1 (555) 555-1212", and then you have 8 digits instead of 7. If you really want to restrict them to 7 digits, you'll have to add your own custom validation:

/^\(?\d{3}\)?[.\s-]?\d{3}[.\s-]\d{4}$/

This will cover all the common variations people use (periods, spaces, dashes, parentheses), and still allow only 7-digit US phone numbers.

Here's a jsfiddle demonstrating the HTML5 validation and normalization:

http://jsfiddle.net/Cj7UG/1/

I hope this helps!



Related Topics



Leave a reply



Submit