0

I'm working on a Java application and ran into a problem that I cannot seem to solve on my own.

I've set a DocumentFilter on JTextField to only allow digit entries, however, the default values are text. I have a button that resets JTextFields back to default, and it is not working presumingly because of the DocumentFilter.

How can I overcome this problem?

Thanks

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
Yury Lankovskiy
  • 143
  • 3
  • 14
  • What's the text? Does it not contain numbers? What's the purpose of the text? – MadProgrammer Apr 02 '14 at 09:45
  • It's a character text. As I said it is default values. – Yury Lankovskiy Apr 02 '14 at 09:51
  • @Yury Lankovskiy could be an interesting question, your requirement to make me sence, but here will based on your SSCCE / MCVE / MCTRE, short, runnable, compilable with hardcoded value in local variables – mKorbel Apr 02 '14 at 09:54
  • @mKorbel I have no idea what you're talking about. – Yury Lankovskiy Apr 02 '14 at 09:58
  • *allow digit entries, however, the default values are text.* How is it possible? Its a contradicting statement. Most probably your document filter is not working as expected. – Braj Apr 02 '14 at 09:59
  • Please have a look at [How to implement in Java ( JTextField class ) to allow entering only digits?](http://stackoverflow.com/questions/5662651/how-to-implement-in-java-jtextfield-class-to-allow-entering-only-digits). – Braj Apr 02 '14 at 09:59
  • @Braj It's not a contradicting statement. When the program loads it has default values, when it's running user is only allowed to input digits. However, there's a button to return back to default settings, which doesn't work because of the filter. I need to somehow overcome this problem. – Yury Lankovskiy Apr 02 '14 at 10:01
  • 1
    The reason I ask is you could use something like `PromptSupport` from SwingLabs SwingX library, for [example](http://stackoverflow.com/questions/20578568/java-swing-listen-an-action-in-a-text-field-of-a-form/20578601#20578601) – MadProgrammer Apr 02 '14 at 10:01
  • @MadProgrammer That looks like what I'm looking for. I'll give it a try and report back. Thanks! – Yury Lankovskiy Apr 02 '14 at 10:02
  • @MadProgrammer Works good and easy to deploy. If you post your answer I'll mark it correct. Thanks – Yury Lankovskiy Apr 03 '14 at 04:26

3 Answers3

4

Do one thing:

store the default document some where

final JTextField textField = new JTextField();
final Document defaultDocument=textField.getDocument();

On button click first set the document back to default to disable the validation on textfield and then set the default text

 btn.addActionListener(new ActionListener() {

    @Override
    public void actionPerformed(ActionEvent e) {
        textField.setDocument(defaultDocument);
        textField.setText("hi");
    }
});

Add you document filter back again on focus in the textfield to validate the user inputs.

Please have a look at How to implement in Java ( JTextField class ) to allow entering only digits?.


-- EDIT --

You can do it by adding focus listener on text field.

If the value in text field is empty then set the default value back as a hint. There is no need to do it on button click.

Here is code:

    final JTextField textField = new JTextField("First Name");

    final Document defaultDocument = textField.getDocument();

    final PlainDocument doc = new PlainDocument();
    doc.setDocumentFilter(new DocumentFilter() {
        @Override
        public void insertString(FilterBypass fb, int off, String str, AttributeSet attr)
                throws BadLocationException {
            fb.insertString(off, str.replaceAll("\\D++", ""), attr); // remove
                                                                     // non-digits
        }

        @Override
        public void replace(FilterBypass fb, int off, int len, String str,
                AttributeSet attr) throws BadLocationException {
            fb.replace(off, len, str.replaceAll("\\D++", ""), attr); // remove
                                                                     // non-digits
        }
    });

    textField.addFocusListener(new FocusListener() {

        @Override
        public void focusLost(FocusEvent e) {
            System.out.println("focus lost");
            if(textField.getText() == null || textField.getText().trim().length()==0){
                textField.setDocument(defaultDocument);
                textField.setText("First Name");
            }
        }

        @Override
        public void focusGained(FocusEvent e) {
            System.out.println("focus gained");
            textField.setDocument(doc);
        }
    });
Community
  • 1
  • 1
Braj
  • 46,415
  • 5
  • 60
  • 76
2

you could use something like PromptSupport

Or maybe the Text Prompt class. It is similar to PromptSupport but can be used on a regular JTextField so you don't need the whole SwingX project.

camickr
  • 321,443
  • 19
  • 166
  • 288
2

A field that the user can only enter numeric data into, but also needs to display non-numeric values is contradictive.

Text is supplied to field via the Document, there is no distinction over how that content is generated, either by the user or programmatically.

If you're trying to display a "prompt" in the field, you can could take a look at PromptSupport in SwingLabs SwingX Library

For Example

Prompt fields

When the fields have focus, the "prompt" will be hidden, but you can control this, making it shown until the user types something or highlight when focus is gained.

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import org.jdesktop.swingx.prompt.BuddySupport;
import org.jdesktop.swingx.prompt.PromptSupport;

public class PromptSupportTest {

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

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

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

    public class TestPane extends JPanel {

        public TestPane() {
            JTextField firstName = new JTextField(10);
            PromptSupport.setPrompt("First Name", firstName);
            PromptSupport.setFocusBehavior(PromptSupport.FocusBehavior.HIDE_PROMPT, firstName);

            JTextField lastName = new JTextField(10);
            PromptSupport.setPrompt("Last Name", lastName);
            PromptSupport.setFocusBehavior(PromptSupport.FocusBehavior.HIDE_PROMPT, lastName);

            JTextField picture = new JTextField(10);
            PromptSupport.setPrompt("Picture", picture);
            PromptSupport.setFocusBehavior(PromptSupport.FocusBehavior.HIDE_PROMPT, picture);

            JButton browse = new JButton("...");
            browse.setMargin(new Insets(0, 0, 0, 0));
            browse.setContentAreaFilled(false);
            browse.setFocusPainted(false);
            browse.setFocusable(false);
            browse.setOpaque(false);
            // Add action listener to brose button to show JFileChooser...

            BuddySupport.addRight(browse, picture);

            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            gbc.weightx = 1;

            add(firstName, gbc);
            add(lastName, gbc);
            add(picture, gbc);

            gbc.anchor = GridBagConstraints.CENTER;
            add(new JButton("Ok"), gbc);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

}

I've also added an example of BuddySupport which is part of the same API, which allows you to "buddy" another component with a text component. Here I've done the classic "file browser" combination, but I do "search" style fields like this all the time...

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366