I know there are many questions on how to focus on a certain text field and so on, but it seems that the issue I am facing is a bit different. So, I have a JTextField which has functionality to autocomplete the text if something that is currently in it has been typed before by the user. I also have a set of buttons that perform insertion of some predefined portion of text into the text field when pressed. The problem is that every time any new text appears in the text field, the autocomplete can trigger and append the text that was used by the user previously. In order to it more friendly, I decided to select the part appended by the autocomplete. All the code is executed in the ED thread. Consider the case when the text field was not in focus :
Both code samples are in the actionPerformed method of the button.
// does not work
if (textField.requestFocusInWindow()) {
textField.getDocument().insertString(...);
}
The insertString() is overriden and has all the logic to select appended string by the autocomplete. So, the only thing I need is that the text field is selected before the string is inserted.
I tried :
// does work
textField.requestFocusInWindow();
SwingUtilities.invokeLater(() -> {
textField.getDocument().insertString(...);
});
The official doc says :
The call to the requestFocusInWindow method initiates the focus transfer, but it does not immediately move the focus ...
This sort of makes sense, since to acquire the focus, a call must be made to the window manager of the clients operating system (that's how I understand that, correct me if I am wrong).
Is the second example working mainly because both events (getting focus and inserting the string) are added to the event queue and the insertion appears after the focus request (actually at the end of the queue) or am I missing something? Is it a valid solution? Can it be done better?
Note: simply adding a listener to the text field ( to react when it is in focus) is not a solution, since the logic I described here is only a part of the whole functionality used.
Related
I will do my best to explain-- I am trying to make a choose-your-own-adventure type game while using a TextField and a TextArea, where what is written in the TextField is appended into the TextArea (this I know how to do via ActionListener).
However, I need to have the TextArea start with a pre-written 'intro', which asks the user at the end if they want to continue or not. Therefore, I need it to be able to scan the user's response ('yes' or 'no') and choose the appropriate selection of pre-written text to follow.
I don't want to overwrite what is already in the TextArea, I want to add to it. I suppose what I'm confused about it how I'm supposed to lay out the entire file so that it functions properly, because the different choices for the adventure span different methods. Having
"String text = textField.getText();" only within the actionPerformed method means I can't use 'text' elsewhere, but moving that line up with my other variables tells me it can't reference the field before it's defined.
I am fairly new to Java and am working on this as a project for a non-programming school course. I've been through many iterations thus far and this is what seems to be my final attempt, as I've remade it repeatedly and don't have much time left. :(
Your questions/comments and my attempts to answer:
I am trying to make a choose-your-own-adventure type game while using a TextField and a TextArea, where what is written in the TextField is appended into the TextArea (this I know how to do via ActionListener).
As per my comment, be sure to create a Swing GUI which would use a JTextField and a JTextArea. You would then add your java.awt.event.ActionListener to the JTextArea, and the ActionListener would respond whenever the user pressed <ENTER> within the JTextField.
However, I need to have the TextArea start with a pre-written 'intro', which asks the user at the end if they want to continue or not. Therefore, I need it to be able to scan the user's response ('yes' or 'no') and choose the appropriate selection of pre-written text to follow.
This can be done easily, but sounds as if you may be trying to shoe-horn a linear console type program into a GUI. If so, consider reconsidering your program design since what works best for one often doesn't work well for another. If you do re-write, then you should consider redoing most including your program flow, but excepting perhaps the "model" portion of your previous program, the "business logic" that underlies everything.
I don't want to overwrite what is already in the TextArea, I want to add to it. I suppose what I'm confused about it how I'm supposed to lay out the entire file so that it functions properly, because the different choices for the adventure span different methods. Having "String text = textField.getText();" only within the actionPerformed method means I can't use 'text' elsewhere, but moving that line up with my other variables tells me it can't reference the field before it's defined.
Again as per comments a JTextArea has an append(String text) method that will add new text to existing text that is already displayed in your JText Area. So on that note, your ActionListener's actionPerformed method could be very simple and look something like:
public void actionPerformed(ActionEvent e) {
String text = textField.getText();
textArea.append(text):
}
Although you may need to add line feeds, "\n" either before and/or after the text you are going to append.
Hello? anyone had a problem like: cursor blinking in more than one field at a time?
In my case the following happens: When you double click on a field JTextField, opens a JDialog, so
after closing this, the focus is directed back to the field clicked before opening the screen.
What happens is that after performing this action, two fields are flashing at the same time (usually the first field
screen, as well as the field in which efetuei double click).
This medium is random, there are cases in which it does not occur.
When debugging the inner class Handler, contained within the class DefaultCaret more specifically the actionPerformed method, realized
that: time is a field, and time is another, which are precisely the fields that are flashing (q seems obvious I know). but they are
the own inner classes of Java that are calling the method.
When passing over the field using the Tab, the cursor false, vanishes.
I'm using JDK 6
I returned the focus within the invokeLater(), but not solved. Now both synchronized flash
The first JComponent focusable is one of the fields that flashing improperly
I'm using my own FocusTraversalPolicy, does that may be influencing? The funny thing is that there is no treatment particularly strange about my class.
I noticed that the standard Java class, using a method within the Syncronized getFirstComponent(), but added the same control, but still is not ok
Actually it's Focus issue for me.
Normally when JTextComponent looses Focus setCaretVisible(false) / setSelectionVisible(false) is called and when Focus gained opposite thing happens.
After closing JDialog try to return Focus inside invokeLater(). Also check what's the first focusable JComponent in the JDialog's parent.
This situation occurs because the project I'm developing is quite large, so do not get small examples of implementation
The project has many components, Tables and Container's, which require focus through at the same time.
It turns out that Swing, put in a queue for execution, a lot of threads, and then dispatching them going, and while he did not finish running it, you can cram grabFocus() or requestFocus(), which does not cry, the first he has to finish everything and then run my request focus.
Resolved palliatively this situation, using the Swing SwingUtilities.invokeLater(...);
Thanks for the tips.
I created a simple app in Netbeans, it contains a few textfields for user input and a button, I've associated an action with the button through the Netbeans interface but I decided to define the action in the App and not the View so as to follow some notion of MVC.
The action works fine, I can print out the console every time the button is clicked.
But in order to do what I want, I need the values included in the jTextFields!
How to do this? This is the code in TestApp.java:
#Action
public void ClickedOnButton() {
System.out.println("Clicked ok");
System.out.println("Will now attempt to read notes.ini");
ReadNotesFile();
}
And this is the code in TestView.java:
javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(tpa_fixer.TPA_FixerApp.class).getContext().getActionMap(TPA_FixerView.class, this);
jButton1.setAction(actionMap.get("ClickedOnButton")); // NOI18N
What have you tried, and how doesn't it work? The standard way to get a JTextField to display text is to call setText() on it. Have you tried doing this?
Also,
Have you gone through the Swing tutorial about these concepts including using text components, JButtons, and ActionListeners?
Are you seeing any errors in these attempts? If so, post them here.
Is your "control" class, the one with the listener code, separate from your "view" or GUI class? If so, does control have a valid reference to view?
Edit
You state:
I don't want to set the text in the jTextFields, I want to get the values out of them and use it in the method that gets run when I click on the button. I can't see how to do this unless I can pass arguments somehow within the body of the action definition in the View class.
What I've done in this situation, where I need to extract information out of gui fields for manipulation in other classes:
You can give each field an associated public getText() method and then call these methods using the control's reference to the view object. For instance say view has a nameField JTextField, then I'd give it a getNameFieldText() method that returns nameField.getText();.
If you had many such fields, then it may be more efficient to use just one getText method but allow it a parameter to let you choose which field to extract text from. To make this work efficiently, I've sometimes given my GUI a HashMap and then have control pass in the String key that allows the getText method to obtain the correct JTextfield, get its text and return it. I often use the same Strings used as JLabels associated with the JTextField as my key Strings.
In my application I have a JTextField that will only allow the user to fill it with input formatted in a certain way. I have a method that checks if input into the field is valid and if not it displays a dialog. After this occurs I would like the focus to return to the text field so that the user can correct there mistake and type in the appropriately formatted input. I tried to do this by having the JTextField call requestFocus() on itself but this seems to only half work. The JTextField displays the flashing cursor but I cannot actually type in any text until I click on the text field again. Is there another method I need to call? I could not find anything else in the documentation.
It's not exactly the solution you asked for, but you might want to look at javax.swing.InputVerifier. This object allows you to verify the input to a field and prevent taking focus away from it if the format isn't right. I don't think it would allow you to put up a dialog explaining the error (though it might - try it) but it would certainly allow you to put a message in a 'message area'.
What you do is set an InputVerifier on the JComponent, have it test the contents for validity; if it isn't right then the JComponent won't release focus (and can write an error message).
I am working on a project that is using a JTable to display, among other things, a column of dates. We needed validation for the user input for dates, so I have implemented a combination of masking for format validation and parsing for actual date validation. I have done this using a custom CellEditor for the date column.
Inside my MaskedCellEditor, I have a JFormattedTextField. I setup the masking for dates. Then I add an InputVerifier to allow for actual validation. My InputVerifier implements verify() to check: 1. textField.isEditValid() 2. DateValidator.ValidDate(). If either is invalid, verify returns false and the InputVerifier locks the focus into the text field (the cell editor) and a small message dialog is displayed reminding the user of the date format.
The error message is a small, undecorated, non-modal, non-focusable JDialog that pops up underneath the cell being edited. It disappears on a keypress or a successful date verification. It is working great except for a small edge case.
If the user selects a menu button on the top of the application while an invalid edit has popped up the dialog, it switches screens, destroying everything currently on the screen (including the table). However, since the dialog is being shown and a keypress/successful edit has not occurred, the dialog is never hidden. It remains visible in a completely unrelated context on a different screen. Once the user has switched off the screen with the table, there is no way for the user to get rid of the dialog.
I have debated throwing either a Timer and/or a MouseListener on the dialog itself that would cause it to disappear, but I feel that I am ignoring the actual problem. The dialog is never being disposed of and I am pretty sure its because it is still set to be visible and it is preventing the garbage collector from getting rid of it.
I have a Cleanup method on the panel holding the JTable, but I cannot find a good way to reference the dialog (a component of the InputVerifier) in order to get rid of it. The dialog is pretty far removed from the table's parent panel. (Panel -> JTable -> CellEditor -> JFormattedTextField -> InputVerifier -> JDialog)
Any ideas on how to force the dialog to be hidden when the table is destroyed? If you need more details, let me know. I'm trying not to get you guys bogged down in the details, but there is a lot going on.
As a first thought, can you not go down the listener approach. If you have a closeErrorDialog() type method that gets called when upon successful valdiation, then you can also call it when a menu action is selected.
As an alternative, perhaps you could control the transition from menu to menu in some way, and create a "cleanup" method which will close down any exisiting error dialogs. This would allow for any other actions that need to take place when changing menus, to happen in the same place.
Just a couple of quick ideas of the top of my head. Hope they are along the lines of what you meant
Many people will vote me down for saying this, but it sounds like your dialog should be modal so that users can't switch away from it without dismissing it first. Or at least disable the menus that allow people to switch away while this dialog is displayed.