Java Forum / GUI / May 2005
How can I stop text field from consuming irrelevant characters?
David Vanderschel - 11 May 2005 22:52 GMT I have a JFormattedTextField formatted with a NumberFormatter. I have set up another component using getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW). I want that component to be able to receive and consume certain alphabetic characters even if that text field has the focus. Unfortunately, when the text field has focus and I type an alphabetic character, the text field accepts and consumes the character. This does not even make sense, since only numeric input can be accepted validly in that field. How can I prevent the text field from consuming these characters which should not be in there in the first place so that my application can process these keyboard events correctly? Or is there some other type of component I should be using for typed numeric input?
My application's window also has some radio buttons and a slider; and, when any of those components has the focus, my application does get the keyboard input events as I intended. So I am not far from the function I seek. The text field is a nuisance for interfering with keyboard input to which it should not even be paying any attention.
Thanks for any pointers, David V.
Vova Reznik - 12 May 2005 15:00 GMT > I have a JFormattedTextField formatted with a > NumberFormatter. I have set up another component [quoted text clipped - 22 lines] > Thanks for any pointers, > David V. javax.swing.text.Document is responsible to change text in the JTexdtComponent. Override Documents void insertString(int, String, AttributeSet);
David Vanderschel - 12 May 2005 17:53 GMT > > Thanks for any pointers,
> javax.swing.text.Document is responsible to change text in the > JTexdtComponent. > Override Documents > void insertString(int, String, AttributeSet); I am but a beginner at java programming. As a result, I have difficulty seeing how the above relates to my problem. I do not really care so much that the alphabetic characters are being _displayed_ in the (supposedly numeric) text field. The problem is that I do not want them to be _consumed_ by that process. I want the characters to be seen by my own application code, not being stopped by the text field implementation.
Given my limited experience with java, I could really benefit from some additional detail.
Regards, David V.
Vova Reznik - 12 May 2005 18:05 GMT >>>Thanks for any pointers, > [quoted text clipped - 18 lines] > Regards, > David V. Simple Example:
class OnlyDigitDoc extends PlainDocument {
public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { for (int i = 0; i < str.length(); i++) { if (!Character.isDigit(str.charAt(i))) { return; } } super.insertString(offs, str, a); } }
yourTextComponent.setDocument(new OnlyDigitDoc());
David Vanderschel - 12 May 2005 21:16 GMT > > Given my limited experience with java, I could really > > benefit from some additional detail.
> Simple Example: > [quoted text clipped - 12 lines] > > yourTextComponent.setDocument(new OnlyDigitDoc()); David Vanderschel - 12 May 2005 21:59 GMT > > Given my limited experience with java, I could really > > benefit from some additional detail.
> Simple Example: > [quoted text clipped - 12 lines] > > yourTextComponent.setDocument(new OnlyDigitDoc()); Though I still fail to understand what this has to do with receipt of keyboard events by another component, I went ahead and attempted to do a setDocument on my JFormattedTextField with an instance of Vova's OnlyDigitDoc. It compiles, but I now get a run time error: ______________________________________________________________________
D:\dv\java\cube>appletviewer 3.html v: 0.0 i: 0 button[i].min: -360.0 button[i].max: 360.0 java.lang.NullPointerException at PuzWin$TextFieldChangeListener.propertyChange(Shrink.java:612) at javax.swing.event.SwingPropertyChangeSupport.firePropertyChange(SwingPropert yChangeSupport.java:264) at javax.swing.event.SwingPropertyChangeSupport.firePropertyChange(SwingPropert yChangeSupport.java:232) at javax.swing.JComponent.firePropertyChange(JComponent.java:3819) at javax.swing.text.JTextComponent.setDocument(JTextComponent.java:401) at javax.swing.JTextField.setDocument(JTextField.java:256) at javax.swing.JFormattedTextField.setDocument(JFormattedTextField.java:685) at PuzWin.<init>(Shrink.java:541) at Shrink.init(Shrink.java:679) at sun.applet.AppletPanel.run(AppletPanel.java:353) at java.lang.Thread.run(Thread.java:534) ______________________________________________________________________
Here is my code at Shrink.java:612: ______________________________________________________________________
/* Listen to the text field. */ public class TextFieldChangeListener implements PropertyChangeListener { public void propertyChange(PropertyChangeEvent e) { float v = ((Number)textField.getValue()).floatValue(); int i = curParam; System.out.println("v: "+v+" i: "+i+" button[i].min: " +button[i].min+" button[i].max: "+button[i].max); ==> slider.setValue(Math.round(720.f*(v-button[i].min)/(button[i].max - button[i].min))); newValue(i, v); } } ______________________________________________________________________
As may be seen from the result of my System.out.println, all my variables are OK, so I don't know what is causing the problem. Until I added the OnlyDigitDoc, the above code worked as I had intended. It is conceivable that the change event is being fired before everything has initialized properly, as I did the setDocument() in the code which builds my frame (window). But I don't understand what is happening well enough to know that.
I don't see that the OnlyDigitDoc object is doing anything at all related directly to keyboard input _events_. I remain totally confused about how anything like this could prevent the characters from being consumed on input. We are not interfering at the level I would expect.
Regards, David V.
Vova Reznik - 12 May 2005 22:07 GMT >>>Given my limited experience with java, I could really >>>benefit from some additional detail. [quoted text clipped - 81 lines] > Regards, > David V. Do you want me to teach you all Swing?
Try this complete example. You cannot type or paste any letters (only digits).
Document is the Model (MVC) in text components.
import java.awt.BorderLayout; import javax.swing.JFrame; import javax.swing.JTextField; import javax.swing.text.AttributeSet; import javax.swing.text.BadLocationException; import javax.swing.text.PlainDocument;
public class CustomDoc extends JFrame {
private JTextField field = new JTextField(new OnlyDigitDoc(), "", 10); public CustomDoc() { getContentPane().add(field, BorderLayout.SOUTH); System.out.println(field.getDocument()); } public static void main(String[] args) { JFrame f = new CustomDoc(); f.setDefaultCloseOperation(EXIT_ON_CLOSE); f.pack(); f.show(); } class OnlyDigitDoc extends PlainDocument {
public void insertString(int offs, String str, AttributeSet a) throws BadLocationException { for (int i = 0; i < str.length(); i++) { if (!Character.isDigit(str.charAt(i))) { return; } } super.insertString(offs, str, a); } } }
David Vanderschel - 13 May 2005 00:49 GMT > Do you want me to teach you all Swing? Certainly not. However, I wish you would address the problem which I described in my opening post. This is not about controlling what can _appear_ in a text field. This is about providing a mechanism so that keyboard input events corresponding to alphabetic keys can be handled by another component in a frame even when a numerically formatted text field has the focus. At present, my text field is _consuming_ the events so that they are not available elsewhere. Other swing components do not do that even though they do listen to the keyboard for certain keys. In this case, I really do not mind so much that the garbage characters echo in the text field. I do mind that they are consumed in the process.
It seems to me that the method that I need override is whatever the text field uses to accept keyboard events in the first place. At that point, I could tell it to ignore alphabetic characters but without consuming them so that the system can hand them to my other component which does want to handle them. However, I have no idea what that method is or how to get to it.
Please carefully reread my initial post and decide if you think that your attempts so far really do address the issue I described. Note also that I closed that message with "Thanks for any pointers". I am not expecting folks to _teach_ me background information. There is plenty of documentation on Sun's Web site and elsewhere. However, if you can see what it is that I am missing conceptually, a pointer to the relevant documentation or even some key words could be a big help.
Regards, David V.
Alan Moore - 13 May 2005 10:05 GMT You can intercept the the key events before the text component sees them with the technique shown here:
http://www.javaspecialists.co.za/archive/Issue007.html
David Vanderschel - 13 May 2005 19:59 GMT > You can intercept the the key events before the text component sees > them with the technique shown here:
> http://www.javaspecialists.co.za/archive/Issue007.html Thank you, Alan! That article actually does address my issue.
Coincidentally, in my frustration with Vova's orthogonal responses, I had managed to find a workaround for my problem last night. I finally managed to bumble onto http://tinyurl.com/dvqq8/. Ahah!: Text fields use an InputMap. Then on http://tinyurl.com/4dn2o/, I found:
To make a component ignore a key that it normally responds to, you can use the special action name "none".
So, all it took was:
InputMap iMap = textField.getInputMap(); // Tell text field to ignore alphabetic characters. char c; for(c='a'; c<='z'; c++) iMap.put(KeyStroke.getKeyStroke(c), "none"); for(c='A'; c<='Z'; c++) iMap.put(KeyStroke.getKeyStroke(c), "none");
(FWIW, I only had to kill alphabetic keys. Bindings I had set up in my other component for some control keys work OK when the text field has focus without my having to mess with the bindings of those keys in the text field. Since alphabetic characters make no sense in this text field, I went ahead and killed all 52 alphabetic characters, even though my program only accepts 12. 40 of them remain without bindings - which is OK.)
My solution strikes me as one which interferes with the intended function of a Swing component - somehow compounding the text field's behaviour with that of my application. (It is also conceivable that I have not gotten sufficiently into the spirit of java programming.) The article Alan cites undoubtedly offers a more systematic approach to the problem. I recognize that my solution is somewhat 'pathological' in terms of structure, but it is simpler and easier to understand. I still think there ought to be a solution which is neither 'pathological' nor complex, which is why I am only willing to call my solution a "workaround". But, since we are not talking about any code that is reusable outside my application, I am going to stop worrying about it now. ;-)
Regards, David V.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|