Moving caret in JTextField using PlainDocument - java

I'm writing a custom control, based on JTextField. My JTextField uses my own Document class, derived from PlainDocument, so that I can process all the user input in overriden insertString(...) and remove(...) methods.
Here's the problem. After I process user input, sometimes I want to move the caret to another position. What is the better way to do it?
By default Document puts the caret next to last input. So I tried to put a char to my target position and delete it immediately. For some reason it doesn't work in remove() method... and the code doesn't look nice :)
Thanks for and proposals.

It seems unnecessary to extend PlainDocument. Simply add a DocumentListener to the Document of your JTextField and you can process the user input in the 3 methods declared in DocumentListener
Use setCaretPosition to move the caret to wherever you would like

You should actually be using a DocumentFilter if you want to control user input. A DocumentFilter allows you to intercept all the input as it happens. You can then use JTextField.setCaretPosition (comes from JTextComponent) to set the caret position. Just pass your DocumentFilter implementation a reference to the JTextField so it can set the caret position for you.
Here's the Java trail for DocumentFilter. Also, an example on JavaRanch.

Related

How to make only the next line of JTextArea (+JScrollPane) editable

So im creating a server, and that works great, however I am a bit stuck on the GUI. You see, I would like it to look just like Command Prompt, where only the next line is editable, and it does not let you delete any other text. So right now I have:
JTextArea ta = new JTextArea();
JScrollPane sp = new JScrollPane(ta);
Then the frame stuff...
f.setTitle("Server");
f.setBounds(ss.width - 600, 50, 550, 350);
f.setResizable(false);
f.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);//added window listener so closes socket connection first
f.setAlwaysOnTop(true);
Then adding it:
f.add(sc);
jt.setBackground(Color.BLACK);
jt.setForeground(Color.WHITE);
//jt.setEditable(false);
Finally, the method I use to output to the TextArea:
public static void append(String text) {
jt.append(text);
jt.append("\n\n"+System.getProperty("user.name")+" / "+getIp()+" > ");
jt.setCaretPosition(jt.getDocument().getLength());
}
Now I need to assign a String to what the user types into the JTextArea after they press enter:>?
jt.addActionListener(...{
public void ActioEvent(ActionEvent e){
String text = JTextArea.getLines().getLastLine().getText().replace(System.getProperty("user.name")+" / "+getIp()+" > ", "");
}
});
Maybe something like that?
Then I need to have it so that only the part after the ">" is editable?
The way to do this is with a DocumentFilter. This is a fairly obscure and little-used part of Java, and is far from easy to use. However it allows you to insert a DocumentFilter between the UI (where rich text content is edited) and the underlying model (the content). You pass all the 'insert' and 'remove' operations through the filter, which can either accept, refuse or modify them. You can code the filter to only permit modifications to the command line, and not to the prompt.
As I say, this is a pretty hard piece of coding, and the Document/DocumentFilter structure has a lot of complexity that your particular application doesn't need. However it does provide you with the facilities you need.
There is a tutorial in the standard Java doc pages, but not an advanced one, and very few examples that I know of are out there on the web.
ProtectedTextComponent (thanks camickr) provides an example of how to do something similar.
Use a Collection a JTextField.
Let the user type on a JTextField, and once he presses enter, move the control to the next JTextField while making the above JTextField uneditable and also remove the JScrollPane from it.
Hope this helps.
I also agree that the JTextArea/JTextField approach is the common and simpler approach.
However if you want to complicate your life a little then you can check out Protected Text Component which will do most of the logic for you.
The current implemtation of the ProtectedDocument only allows you to add protection to the Document, not remove it so the first thing you will need to do is add a method to "Clear" all the protect pieces of text. This is easy enough, you just clear the entries in the Map used by the class.
Next you will need to replace the default "Enter" Action used by the JTextPane. You do this by playing with the Key Bindings of the text area. See Key Bindings for some basic information. In your custom Action you would first need to invoke the newly created "clear(...)" method. Then you would add you text to the text area. Finally you would protect all the text but the last "x" number of characters.

Clarification on modifying a Document's contents from a DocumentListener

From the Swing tutorial on text components:
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.
I am confused. So what is the correct way to change the text eg. as a result of a KeyEvent ?
1) using DocumentListener for
output from JTextComponent to the GUI
HightLighter or Styled text
2) DocumentFilter for filtering of
unwanted chars,
chars sequence(s),
these filtered chars could be
replaced with another char (or with defined chars sequence)
removed (never will be displayed in the JTextComponent)
3) similair funcionality to provide JFormattedTextFieldis possible to input to the JTextComponent only chars 0 - 9, decimal separator, negative sing,
4)
So what is the correct way to change the text eg. as a result of a KeyEvent ?
use DocumentFilter
A direct answer is using SwingUtilities.invokeLater() placing the Document modification code there. But mKorbel's answer (+1) covers most of the cases you can imagine.
The text say's that you may want to use a document listener. Here is a example how to write one.
A Swing text component uses a Document to represent its content.
Document events occur when the content of a document changes in any
way.
So, always that your text component changes the document listener will fire, but the text says that you cannot change the value of the component in this listener.
In a KeyListener (that's not a document listener) you can change the value using setText().
Depending on what you want, i suggest you look DocumentFilter.

Reading text from JTextArea in java

I have a JTextArea in my Java program... I want that if I write an asterix (*) in the JTextArea, the output will be ATX as a text... can someone help me please?
you can do this
if(yourTextArea.getText.contains("*"))
{
yourTextArea.setText("ATX");
}
You can add a key listener to it, so when ever a key is typed, you check to see if it is an * and if it is replace it with the ATX
Oops, misread the question.
If you want to do this constantly, then the only way is through a keyListener:
http://download.oracle.com/javase/tutorial/uiswing/events/keylistener.html
In my opinion, this would probably be pretty annoying functionality for it to change one character to 3 characters as the user types. Consider doing it when the user does some method, in which case you wouldn't need a listener.
Do you mean:
String s = YourTextArea.getText().contains("*") ? "ATX" : YourTextArea.getText();
Please clarify your question so that we can help you
It sounds like you want to capture the user's input and then determine if you want to do something with it or not depending on what it is.
First off, you will need to add an action listener to this JTextArea to listen for whatever the user types so you can determine what it is. You would do this with a KeyListener. Next you need a way of determining where the caret is positioned in the JTextArea. You would do this with a CaretListener.
Now when ever a KeyPressed event occurs, you will need to determine what the key is. If it is in fact an asterisk * you will insert the text ATX into the JTextArea at the current position of the caret.
You will then use something like:
textarea.insert("ATX", pos);
Where textarea is the JTextArea object and pos is an integer that holds the current position of the caret within the JTextArea. If you are not sure how to get the caret position read up on the CaretListener API. It has everything you will need.
Output where? Into this text area itself? So, in other words do you want to implement some kind of alias?
In this case you can add KeyListener and in its keyTyped() implement your logic: if key is * add to text area your text.

Input-validation based on entire content of JTextField, not just the last typed character

Is there a way to validate text in a JTextField while you type, based on what you already typed in that field? Should I create a keyEventListener of some sort, or is there a way to override the insertString method to let it do that. I prefer the latter, but it only gives you control over the last character that was typed, not the entire string of text already present in the text field. I want it to beep as soon as one tries to enter more than one decimal point, and not adding that second decimal point to the text field.
Thanks for your help,
Erik
What's the problem with adding a listener? That's what they are there for.
You might also want to have a look at JFormattedTextField.

How can I create an AutoComplete popup in a JTextPane in Java?

I am creating a SQL editor. I am using JTextPane for the editor. I want to implement AutoCompletion for table name etc. like Eclipse.
I think the appropriate class for displaying info on top of another component is JPopupMenu, which already handles layering correctly to display itself. JPopupMenu has a show() method that takes its 'parent' component as an argument, and it will show itself in that component's coordinate space. Since you want to display a selection of terms for the user to choose from, a menu seems appropriate.
To check for text changes, you'd add a DocumentListener to the document that's wrapped by the JTextPane; you can access it using getDocument().
To find out where the cursor (actually, the caret) is, you can use getCaretPosition(). That returns the caret's position within the text stream as an int. You can use modelToView() to translate that position to actual (x,y) coordinates. That in turn will tell you where to show your menu.
You can use addKeyListener() to catch keyboard events on your JTextPane, like hitting Ctrl-Space.
The combination of all that should allow you to do what you're looking to do.
You can also use http://fifesoft.com/autocomplete/. You can install it on any JTextComponent.
For things like this you probably should consider layered panes so your auto-complete suggestions appear in the correct place and z-order.
Furthermore you will have to look for changes in the JTextPane to know when the user is typing and you will need a parser that understands what is typed so you can offer the feature only at appropriate points.
It's not quite clear what exactly your problem is and what you got so far.
I achieved this by adding a key listener to the JTextPane and checking for CTRL + Space keystrokes. When the appropriate key combo was detected the listener went off and looked up the list of possible matches based on the characters directly to the left of the cursor at the time of the key press and found the best matches and displayed them to the user in a JPopup. If there was an exact match then it simply replaced the partial text with the match. If no matches were found an option was given to the user to add the text that they had already typed, edit it and record it into the list of acceptable data.
We use jide. They have a lot of components that help you do this kind of thing really easily

Categories

Resources