17

Is it possible to discover which oject generated a DocumentEvent? Something like i can do with ActionListener:

JTextField field = new JTextField("");
field.addActionListener(actionListener);

//inside ActionListener
public void actionPerformed(ActionEvent arg0) {
  if (arg0.getSource() instanceof JTextField) //true

}

I would like to do the same with DocumentEvent but seems not to work the same way:

JTextField field = new JTextField("");
field.getDocument.addDocumentListener(documentListener);
//inside documentListener
public void insertUpdate(DocumentEvent){
  if (arg0.getSource() instanceof JTextField) //false: class is javax.swing.text.PlainDocument
  if (arg0.getSource() instanceof MyComponent){
      MyComponent comp = (MyComponent)arg0.getSource();
      comp.callSpecificMethodUponMyComp(); 
  }
}

The answser should take in consideration the following points:

  1. For my purposes knowing the object type that generated the event isn't enough, but i need a reference to it at runtime.
  2. Typically the events are generated from extension of the swing object (myComp public JTextField). These objects store additional information that should be retrieved at runtime inside the listener method (es. insertUpdate)
  3. DocumentListener is implemented from a class that is unaware of the fields that generated the events. Differents fields of differents types can be attacched to the listener at runtime.
mKorbel
  • 109,525
  • 20
  • 134
  • 319
Heisenbug
  • 38,762
  • 28
  • 132
  • 190

3 Answers3

30

You can set a property in the document to tell you which textcomponent the document belongs to:

For example:

final JTextField field = new JTextField("");
field.getDocument().putProperty("owner", field); //set the owner

final JTextField field2 = new JTextField("");
field2.getDocument().putProperty("owner", field2); //set the owner

DocumentListener documentListener = new DocumentListener() {

     public void changedUpdate(DocumentEvent documentEvent) {}

     public void insertUpdate(DocumentEvent documentEvent) {

         //get the owner of this document
         Object owner = documentEvent.getDocument().getProperty("owner");
         if(owner != null){
             //owner is the jtextfield
             System.out.println(owner);
         }
     }

     public void removeUpdate(DocumentEvent documentEvent) {}

     private void updateValue(DocumentEvent documentEvent) {}
};

field.getDocument().addDocumentListener(documentListener);
field2.getDocument().addDocumentListener(documentListener);

Alternatively:

Get the document that sourced the event and compare it to the document of the textfield.

Example:

public void insertUpdate(DocumentEvent documentEvent) {
    if (documentEvent.getDocument()== field.getDocument()){
        System.out.println("event caused by field");
    }
    else if (documentEvent.getDocument()== field2.getDocument()){
        System.out.println("event caused by field2");
    }
}
dogbane
  • 266,786
  • 75
  • 396
  • 414
  • Thank you for your reply. Quite useful but it isn't enough for my design. I edited my question trying to explain better which are my needings – Heisenbug Mar 08 '11 at 07:20
  • 3
    The first version of this answer, which sets an 'owner' property, seems to fit perfectly with the question (cool tip btw, I didn't know about that!). Can you explain more specifically why this doesn't satisfy your needs? – Jesse Barnum Mar 09 '11 at 12:24
  • @Jesse Barnum : i think you are right. Actually i have misunderstood dogbane first answer that was perfect. In fact if i want have a direct reference to the type MyComponent i can do something like field.putProperty("MyComponent", anInstanceOfMyComponent) , right? (i'm feeling a bit stupid now :( , maybe too lines of code these days made me confused) – Heisenbug Mar 09 '11 at 22:51
3

Rather than add multiple fields to the same listener. Create a custom listener that upon creation takes a reference to the text field. Then create a new instance of the listener each time you add it to a field.

jzd
  • 23,473
  • 9
  • 54
  • 76
  • yes ..maybe a good solution thanks. But my listeners are many and they are quite big objects.. having multiple instances of them may not be a good idea. – Heisenbug Mar 09 '11 at 23:22
  • 1
    You could break out your listeners into their own class that makes calls to the big object. – jzd Mar 10 '11 at 00:01
0

The attempt with the document property is equivalent to an independent

Map<javax.swing.text.Document, javax.swing.JTextField> textFields;

The suggested extension of the listener could be

public void bind(JTextField tf)
{
    final Document doc = tf.getDocument();
    textfields.put(doc, tf);
    doc.addDocumentListener(this);
}
Sam Ginrich
  • 661
  • 6
  • 7