Search code examples
javaswingpaneltextfieldjoptionpane

Using Panel of TextFields in JOptionPane, DocumentListener? - Beginner


Edited to add the setName function:

I've been using stackoverflow for over a year to help with learning java after only about 6 hours of CS in college. You guys are the best! So getting to it...

My problem is that I've got a JOptionPane with multiple textFields. All the examples of retreiving the text from these fields only show a single textField. I could create a separate DocumentListener for each textField that handles each box separately, but it just seems that there should be a way to create one DocumentListener that can say :

if(namebox changed)

edit name

else if(dataBox changed)

edit data

etc....

Here is my code as it originates:

    public class HumanPlayer extends Player
    {
    /**
     * Constructor for objects of class HumanPlayer
     */
    public HumanPlayer()
    {
        setName("Human " + getOrder());
    }


    @Override
    public void chooseSoldiers()
    {
        JLabel nameLabel = new JLabel("Enter name: " );
        //humans.setPreferredSize(new Dimension(100,50));


        final JTextField nameBox = new JTextField();
        final JTextField infantryBox = new JTextField();
        final JTextField scoutBox = new JTextField();
        final JTextField sniperBox = new JTextField();
        JLabel infLabel = new JLabel("Infantry: " );
        JLabel scLabel = new JLabel("Scouts: " );
        JLabel snLabel = new JLabel("Snipers: " );

        JPanel soldierPanel = new JPanel();
        soldierPanel.setLayout(new GridLayout(4,2,5, 8));
        soldierPanel.add(nameLabel);
        soldierPanel.add(nameBox);
        soldierPanel.add(infLabel);
        soldierPanel.add(infantryBox);
        soldierPanel.add(scLabel);
        soldierPanel.add(scoutBox);
        soldierPanel.add(snLabel);
        soldierPanel.add(sniperBox);

        nameBox.getDocument().addDocumentListener(new NameListener());
        infantryBox.getDocument().addDocumentListener(new NameListener());
        scoutBox.getDocument().addDocumentListener(new NameListener());
        sniperBox.getDocument().addDocumentListener(new NameListener());

        int ok = JOptionPane.showOptionDialog(null, soldierPanel,  
                "Player " + getOrder(), JOptionPane.CANCEL_OPTION,  
            JOptionPane.QUESTION_MESSAGE, null, null, null);        
       }

    public class NameListener implements DocumentListener
    {

        @Override
        public void changedUpdate(DocumentEvent e) {}
        @Override
        public void insertUpdate(DocumentEvent e) {
            try {
                   setName(e.getDocument().getText(0,e.getDocument().getLength()));
            } catch (BadLocationException e1) {e1.printStackTrace();}

        }

        @Override
        public void removeUpdate(DocumentEvent e) {
            try {
                setName(e.getDocument().getText(0,e.getDocument().getLength()));
            } catch (BadLocationException e1) {e1.printStackTrace();
                }               
           }
    }
}

Separate File:

public abstract class Player
{
....
private String name;
 ....

public void setName(String _name)
{
    name = _name;
}

Solution

  • If i am understanding you correctly, you want to use one document listener and get it responding with all the JTextFeild data change event. Unfortunately, a DocumentListener's event sources are the Documents to which is registered using addDocumentListener function, not the text component. SO the idea is to use:

    1. Document's putProperty("owner", txtFeild): to track the owner text field of this Document
    2. On Document change event use getProperty("owner") to get the owner of the event source: document instance.
    3. assigning PropertyChangeListener to each text field to set this property to their own document: as it is unpredictable if a new document's is set to the TextComponent we are using.

    Check the following code snippets carefully:

        class MyDocumentListener implements DocumentListener{
    
           public void updateComponent(DocumentEvent e)
           {
                boolean valid = checkDataValidity(e.getDocument());
                JTextField txtField = (JTextField) e.getDocument().getProperty("owner");
    
               if(!valid)
                 txtField.setEnabled(false);
               else  txtField.setEnabled(true);
           }
    
             @Override
             public void insertUpdate(DocumentEvent e) {updateComponent(e);}
    
             @Override
             public void removeUpdate(DocumentEvent e) {updateComponent(e);}
    
             @Override
             public void changedUpdate(DocumentEvent e) {}
         }
    
        class MyPropChangeListener implements PropertyChangeListener{
    
           DocumentListener documentListenr;
    
           public MyPropChangeListener(DocumentListener documentListener) {
                 this.documentListenr = documentListener;
           }
    
           @Override
           public void propertyChange(PropertyChangeEvent evt) {
               System.out.println("chaning document!!");
               JTextField txtFeild =  (JTextField)evt.getSource();
               txtFeild.getDocument().putProperty("owner", txtFeild);
               txtFeild.getDocument().addDocumentListener(documentListenr);
            }
         }
       //..............
    
       MyPropChangeListener propChangeListener = new MyPropChangeListener(new MyDocumentListener());
    
        jTextField1.addPropertyChangeListener("document", propChangeListener);
        jTextField1.setDocument(new PlainDocument());
    
        jTextField2.addPropertyChangeListener("document", propChangeListener);
        jTextField2.setDocument(new PlainDocument());