can't clear jtextfield using Documentlistener - java

i have a textfield, when the user inserts a certain number of characters the program should put it in a JTable and clears the textfield, but it fires an event for Jtextfield.setText("");
Here's my code:
jTextField2.getDocument().addDocumentListener(new DocumentListener() {
#Override
public void insertUpdate(DocumentEvent e) {
printIt();
}
#Override
public void removeUpdate(DocumentEvent e) {
}
#Override
public void changedUpdate(DocumentEvent e) {
}
private void printIt() {
//DocumentEvent.EventType type = documentEvent.getType();
String code=jTextField2.getText().trim();
// if(type.toString().trim().length()==13)
if (code.length()==4) {
list.add(code);
mod.addRow(new Object[]{code});
jTextField2.setText("");
}
}
});
}

To update the text field while using a DocumentListener you need to wrap the code in a SwingUtilities.invokeLater() so the code is executed after all updates have been done to the Document.
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
jTextField2.setText("");
}
});

You can't modify the textfield's doucment inside a DocumentListener. Use a DocumentFilter to modify text.
Document listeners should not modify the contents of the document; The
change is already complete by the time the listener is notified of the
change. Instead, write a custom document that overrides the
insertString or remove methods, or both.
In another part.
You may want to change the document's text within a document listener.
However, you should never modify the contents of a text component from
within a document listener. If you do, the program will likely
deadlock. Instead, you can use a formatted text field or provide a
document filter.
All quotes from here
Tutorial How to write a DocumentFilter

Related

How to remove Focus Listener from the JFormattedTextField, in my example of the code?

I am having trouble removing focus listener after adding it to JFormattedTextField. I read about removeFocusListener, but couldn't find examples how to use it. It seems easy enough but no matter what I try it wouldn't work.
Here's a relevant part of the code, where I add the listener, do what I need with it, and where I want to remove it:
private JFormattedTextField heightArea;
heightArea.addFocusListener(new FocusListener() {
#Override
public void focusGained(FocusEvent e) {
heightArea.setText(getHeight(widthArea));
}
#Override
public void focusLost(FocusEvent e) {
}
});
// From here on I want to remove this listener.
I would try things like:
heightArea.removeFocusListener(new FocusListener() );
or
heightArea.removeFocusListener(heightArea.FocusListener() );
But of course it didn't work. I am not really sure what I should pass to the removeFocusListener from heightArea to remove that focus listener.
Sorry for my inexperience, hopefully you can point me towards the right direction, so I could understand what I am doing wrong.
Any help is appreciated, thank you very much.
Create a class MyFocusListener and declare a class level variable of the same type. Something like this
MyFocusListener myFocusListener = new MyFocusListener();
class MyFocusListener implements FocusListener {
#Override
public void focusGained(FocusEvent e) {
// add your logic here
}
#Override
public void focusLost(FocusEvent e) {
}
}
Then add/remove this listener to your textfield
heightArea.addFocusListener(myFocusListener);
heightArea.removeFocusListener(myFocusListener);
I used heightArea.removeFocusListener(this) in focusLost, which solved my issues.

java Swing how consume document event

I want consume a DocumentEvent captured into insertUpdate method of a DocumentListener
I don't see any way to prevent as a KeyEvent (e.consume()).
I don't want use the key listener because can't prevent the clipboard events (Copy Paste).
How I work with this events?
How I can raise Document events since cose?
Isbn13TextField.getDocument().addDocumentListener(new DocumentListener(){
public void insertUpdate(DocumentEvent e) {
e.consume(); //Not Exists, How consume a copy paste?
}
public void removeUpdate(DocumentEvent e) {}
public void changedUpdate(DocumentEvent e) {}
});
Depending on what it is you are trying to achieve...
You could...
Use a DocumentFilter which will allow you to filter input before it reaches the underlying Document. This is used by the Document itself and therefore is not depended on how the content is being added/removed from the Document but the Document itself.
Take a look at Text Component Features and Implementing a Document Filter in particular and here for examples
You could...
Make the field non-editable...
Isbn13TextField.setEditable(false)
How consume a copy paste?
You can't. A DocumentEvent is generated AFTER the Document has already been updated.
If you just want to disable the copy/paste functionality of a text field then you can remove the Key Bindings:
KeyStroke copy = KeyStroke.getKeyStroke("control C");
textField.getInputMap().put(copy, "none");

How do I update a JComboBox's list from a Document Listener?

I'm writing a custom JComboBox and whenever the user types something I want to update the drop down menu of my JComboBox. The issue I'm having is that once my DocumentListener sees an update I get an error when I try to add an item to the list.
Here's a basic example of what isn't working:
public class InputField extends JComboBox<String> implements DocumentListener{
//when something is typed, gets suggestions and adds them to the popup
#Override
public void insertUpdate(DocumentEvent ev) {
try{
giveSuggestions(ev);
}
catch(StringIndexOutOfBoundsException e){
}
}
private void giveSuggestions(DocumentEvent ev){
this.addItem("ok");
}
This isn't actually how my program will work (I'm not just going to add OK each time someone types something), but getting this to work would allow me to implement my custom JComboBox the way it needs to work. Thanks in advance for any help.
EDIT: The error message I get is:
Exception in thread "AWT-EventQueue-0" java.lang.IllegalStateException: Attempt to mutate in notification
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
this.addItem("ok");
// I can never remember the correct way to invoke a class method
// from witin and anonymous inner class
//InputField.addItem("ok");
}
});
maybe this is what you are looking for
jComboBox2.getEditor().getEditorComponent().addKeyListener(new java.awt.event.KeyAdapter() {
public void keyReleased(java.awt.event.KeyEvent evt) {
//add your handling code here:
} });

Using Actions with DocumentListener

I'm developing an application where I want something to be triggered both by the user updating the contents of a JTextArea, or manually via pressing a JButton.
I have done the first part using a DocumentListener and putting the relevant code in its insertUpdate method.
I haven't used Actions before, but I've heard they are useful for situations where you need something to be triggered by multiple controls. Is it possible to trigger the action from the DocumentListener? Is it a good idea to use Actions at all, or should I just put my code in a normal method?
(in the constructor):
textAreaInput.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
// do something
}
public void removeUpdate(DocumentEvent e) {}
public void changedUpdate(DocumentEvent e) {}
});
and the Action, which is a field:
Action doSomething = new AbstractAction("Do Something!") {
#Override
public void actionPerformed(ActionEvent e) {
// do it
}
};
clarification:
The JTextArea will receive text that is pasted in by the user, which I want to parse automatically. The parsing depends on other values set elsewhere in the GUI; if the user changes these other values, he may want to re-parse the text, hence the need to perform the same action by pressing a button.
I want something to be triggered both by the user updating the contents of a JTextArea, or manually via pressing a JButton.
This doesn't make sense to me.
Why would clicking a button invoke the same Action as a user typing text into a text area?
I haven't used Actions before, but I've heard they are useful for situations where you need something to be triggered by multiple controls
That statement is meant for controls that the user clicks, like JMenuItems, JButtons or hitting Enter on a text field. In general they can be used when you use an ActionListner.
A DocumentListener is not an ActionListener so as I stated earlier the use of an Action doesn't seem appropriate.
I think you need to clarify your requirement.
Edit, based on clarification
if the user changes these other values, he may want to re-parse the text
Why does the user have a choice? If you change the font, text, foreground, background of a text area, the component it automatically repainting, you don't have to ask for this to be done. If you look at the code for these methods they always end up invoking the revalidate() and repaint() methods.
The parsing depends on other values set elsewhere in the GUI;
Sounds like you need a custom class. Maybe a ParsedTextArea or ParsedDocument. This class would contain the "properties" that can be set elsewhere in the GUI. It would implmenent the DocumentListener. It would also support your "parseTheText" method. So whenever a property is changed or a DocumentEvent is generated you automatically invoked the "parseTheText" method. This way you don't need a separate button and the component will always be in sync because the parsing is automatic.
You can invoke the actionPerformed() method, whether it's in an Action or not. There's an example here.
I think you need not create the Action object. You can add ActionListener to the Button just like you have added DocumentListener to the Document of the input. If I correctly understand your problem, may be you should do something like this:
textInput.getDocument().addDocumentListener(new DocumentListener(){
#Override
public void insertUpdate(DocumentEvent e) {
doIt();
}
#Override
public void removeUpdate(DocumentEvent e) {}
#Override
public void changedUpdate(DocumentEvent e) {}
});
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
doIt();
}
});
doIt() is a method in which you will do what you wanted to do.

Trigger a button when exactly 13 characters in text field

I have a text field and a Search button. If the user enters precisely 13 digits (a barcode) then I want to trigger the Search automatically.
I have a DocumentListener on the text field and am processing the insertUpdate method to determine that 13 digits have been entered. I could call the search code directly at that point (and it does work) but although the 13th character has been typed, it isn't actually displayed on the screen until the search has completed.
I would prefer instead to trigger the Search button and have tried two ways:
DocumentListener dlBarcode = new DocumentAdaptor() {
public void insertUpdate(DocumentEvent e) {
String value = jtBarcode.getText();
if (isBarcode(value)) {
ActionEvent ae = new ActionEvent((Object)jbSearch,
ActionEvent.ACTION_PERFORMED, "");
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(ae);
}
}
};
The second is to use:
jbSearch.dispatch(ae);
Neither method appears to cause the ActionListener on jbSearch to be triggered. Can you please suggest what I am doing wrong?
Don't try programatically "click" the button. It's not being pressed, so why try to fool your code into thinking it is? Separating an action from the gesture that performed the action is an important principle to follow. By analogy, think of the ignition on your car. Turning the key triggers the ignition. So if I wanted to design a remote car starter, would I create a mechanical robot that physically inserts and turns a key, or should my system simply signal the ignition directly?
Simply define a method, call it performSearch or whatever, and have both your ActionListener on the button and your DocumentListener each call that method on their own.
One note: don't forget to actually register your document listener with the text control you're using.
I could call the search code directly at that point (and it does work) but although the 13th character has been typed, it isn't actually displayed on the screen until the search has completed.
Wrap the call to the search code in a SwingUtilities.invokeLater(). This will place the search at the end of the Event Dispatch Thread, so the text field will be updated before the search is started.
DocumentListener dlBarcode = new DocumentAdaptor() {
public void insertUpdate(DocumentEvent e) {
String value = jtBarcode.getText();
if (isBarcode(value)) {
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
invokeSearchMethod();
}
});
}
}
};
camickr's suggestion of using invokeLater strangely didn't work as the 13th character didn't get painted until the search had finished. Mark's comment suggesting using a SwingWorker did the trick. My DocumentListener code now looks like:
DocumentListener dlBarcode = new DocumentAdaptor() {
public void insertUpdate(DocumentEvent e) {
String value = jtBarcode.getText();
if (isBarcode(value)) {
PerformSearch ps = new PerformSearch(value);
ps.execute();
}
}
And my PerformSearch looks like:
class PerformSearch extends SwingWorker<Product, Void> {
private String key = null;
public PerformSearch(String key) {
this.key = key;
}
#Override
protected Product doInBackground() throws Exception {
return soap.findProduct(this.key);
}
protected void done() {
Product p = null;
try {
p = get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
prod = p;
if (prod != null) {
... populate text fields
}
else {
... not found dialog
}
}
Thanks for the help. Much appreciated.

Categories