I have a Form with various textboxes(say around 10) .After the user fills value in each textbox, it is validated on focuslost event for the textbox.
public void focusLost(FocusEvent e)
{
JTextField tf = (JTextField)(e.getSource());
String finalVal = tf.getText();
try
{
validate(finalVal);
}
catch(NmfException ex)
{
JOptionPane.showMessageDialog(parent, message, title,
JOptionPane.ERROR_MESSAGE);//Error Message is passed
/* Error pop up is displayed when validation fails. Message text with an 'Ok' button is displayed and the code waits for ok to be clicked to execute rest of the code*/
tf.setText(defaultVal);//Value is reset to default value
return;
}
}
The form has a 'Add' button which gets the values from the UI(from the textbox) and sends it to the server.Ideally, since the values are validated at each textfield the value sent to the server should be valid inputs.
But my issue is, when an invalid input is given to a textfield(say -5 an invalid input) and 'Add' button is clicked at once.
The focusLost event is triggered and the pop up is obtained,while the code waits for the 'OK' button in pop up to be pressed,the next event of button clicked is also called.So before the defaultVal can be set as textfield value,the Add button operation is done(there is no further validation in add operation) and invalid inputs are sent to the server.
How can ensure that Add operation is called only after the focusLost event operation is done.Please suggest a fix for the issue? What would be a best practice for such a scenario?
Set one Flag which should be check while click on 'Add'.
So if all validation should be true/OK then send to server.
if flag is false/invalid, while click on 'Add' then give user prompt
with error message.
As per your scenario if any one try to add invalid value then
focusLost event makes Flag -> false, and vice-versa.
Likewise need to design architecture of coding.
You could also use a mouse listener on the text fields, and validate in the mouseExited method
Related
I'm currently creating a dialog using JavaFX. The Dialog it self works very well but now I'm trying to add an input validation which warns the user when he forgets to fill out a text field.
And here comes my question: Is it possible to prevent the dialog from closing inside the Result Converter? Like this:
ButtonType buttonTypeOk = new ButtonType("Okay", ButtonData.OK_DONE);
dialog.getDialogPane().getButtonTypes().add(buttonTypeOk);
dialog.setResultConverter((ButtonType param) -> {
if (valid()) {
return ...
} else {
Alert alert = new Alert(Alert.AlertType.WARNING);
alert.setHeaderText("Pleas fill all fields!");
alert.showAndWait();
//prevent dialog from closing
}
});
I noticed that the dialog dosn't close if an error was thrown inside the resault converter but this doesn't seems to be a good way to solve this problem.
If it isn't possible to solve the problem this way I could disable the button as described in this post. But I would prefer to keep the button enabled and display a message.
Thank you in advance !
How you are supposed to manage data validation in a dialog is actually explained in the Javadoc, I quote:
Dialog Validation / Intercepting Button Actions
In some circumstances it is desirable to prevent a dialog from closing
until some aspect of the dialog becomes internally consistent (e.g. a
form inside the dialog has all fields in a valid state). To do this,
users of the dialogs API should become familiar with the
DialogPane.lookupButton(ButtonType) method. By passing in a ButtonType
(that has already been set in the button types list), users will be
returned a Node that is typically of type Button (but this depends on
if the DialogPane.createButton(ButtonType) method has been
overridden). With this button, users may add an event filter that is
called before the button does its usual event handling, and as such
users may prevent the event handling by consuming the event. Here's a
simplified example:
final Button btOk = (Button) dlg.getDialogPane().lookupButton(ButtonType.OK);
btOk.addEventFilter(
ActionEvent.ACTION,
event -> {
// Check whether some conditions are fulfilled
if (!validateAndStore()) {
// The conditions are not fulfilled so we consume the event
// to prevent the dialog to close
event.consume();
}
}
);
In other words, you are supposed to add an event filter to your button to consume the event in case the requirements are not fulfilled which will prevent the dialog to be closed.
More details here
One other way to solve this is by using setOnCloseRequest if you don't want to relay only on the user clicking the "Okay" button. The event handler will be called when there is an external request to close the Dialog. Then the event handler can prevent dialog closing by consuming the received event.
setOnCloseRequest(e ->{
if(!valid()) {
e.consume();
}
});
I am trying to create a GUI for my program. This particular GUI uses a JOptionsPane with a showOptionDialog. I have added a panel to that OptionsPane that has some action listeners as well as two lists and some other things, that really doesn't matter for this question though.
Quite simply I want my showOptionDialog to perform some action when the user clicks the "cancel" button. (It will basically end the program but it must be done in a certain way). Right now when the user clicks "cancel" the program continues as if the user just ended that dialog but no action is taken. I am trying to change a variable if they click cancel which will prevent the rest of the program from running. I tested with a System.out.println to see if my value was really being changed and I found that the step wasn't occurring at all. So I would like to know based upon this code what I am doing wrong. What do I need to do to make the code run correctly when the user clicks cancel?
I do not have more code to show as my program is very large and it is impossible for me to isolate this situation.
Thanks in advance for the help!
public static void displayGUI(){
int result = JOptionPane.showOptionDialog(null, getPanel(),"JOptionPane Example : ", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, new String[]{"Confirm","Create Return"}, "default");
if(result == JOptionPane.CANCEL_OPTION){
initialScreenDecisions="NONE";
MainWriter.finishedCounter=true;
System.out.println(MainWriter.finishedCounter);
while(MainWriter.entryDetails.size()>0){
MainWriter.entryDetails.remove(0);
}
while(output.size()>0){
output.remove(0);
}
}
}
*This part of the code isn't being executed, even if the user selects cancel:
if(result == JOptionPane.CANCEL_OPTION){
initialScreenDecisions="NONE";
MainWriter.finishedCounter=true;
System.out.println(MainWriter.finishedCounter);
while(MainWriter.entryDetails.size()>0){
MainWriter.entryDetails.remove(0);
}
while(output.size()>0){
output.remove(0);
}
}
From your Question:
*This part of the code isn't being executed, even if the user selects cancel:
Try The integer value that is returned from the JOptionPane.showOptionDialog(). 0 Is returned if OK is selected and 1 is returned if Cancel is selected.
Modify your code as follows:
if(result == 1){
initialScreenDecisions="NONE";
MainWriter.finishedCounter=true;
System.out.println(MainWriter.finishedCounter);
while(MainWriter.entryDetails.size()>0){
MainWriter.entryDetails.remove(0);
}
while(output.size()>0){
output.remove(0);
}
}
Let me Know, If this doesn't Helps you!!!
You are telling JOptionPane to create two buttons ("Confirm" and "Create Return"), and then telling it the default button is "default" but you don't have a button with text "default". You also don't have a Cancel". The return value will be 0 if the uses picks "Confirm", or 1 if the user picks "Create Return", or CLOSED_OPTION if the user just closes the dialog.
If you take a look at the JavaDocs for JOptionPane.showOptionDialog, it tells you
Returns: an integer indicating the option chosen by the user, or
CLOSED_OPTION if the user closed the dialog
This is the index of the options array you passed to the method. In this case new String[]{"Confirm","Create Return"}
So a return value of 0 will mean Confirm was selected and 1 will mean Create Return was selected (or JOptionPane.CLOSE_OPTION if the user closed the window)
When assigning result a value you are using JOptionPane.OK_CANCEL_OPTION but in the if condition you are checking for JOptionPane.CANCEL_OPTION
I'm building a chat program. The user has the option to press a JButton SEND or just press ENTER on the keyboard to send the message. This is my code.
private void chatTextAreaKeyPressed(java.awt.event.KeyEvent evt) {
if(evt.getKeyCode() == KeyEvent.VK_ENTER) {
this.sendButtonActionPerformed(null);
this.chatTextArea.setText(null); // Clear JTextBox
}
}
The problem with this, is that after pressing ENTER, it sets the JTextBox with a empty new line. So that whatever I type next will always be on the second line instead of starting with an empty text box.
Anyone has any ideas? Much appreciated.
You need to consume the event with evt.consume() to ensure it isn't processed by the text field itself.
This indicates that all processing of the event has finished and no other listeners should act upon the event.
I have a textbox with attached ModifyListener.
In implemented modifyText(ModifyEvent e) I execute desired functionality.
The problem with that, that this event is triggered on every text change.
I don't want it to trigger if text was altered programmaticly (by setting text via code).
I want it to trigger only when user changes the code (I can't use keylistener because it will be triggered also when user click on arrow buttons and etc, it also won't detect if user copy&paste text)
You could unregister your ModifyListener before calling setText(..) and reregister it afterwards.
How about textBox.addKeyListener(...) and textBox.addMouseListener(...) instead of ModifyListener?
You can try using Focusout listener.... then you will get the value which user has entered only once.
Text text;
text.addListener(SWT.FocusOut, new Listener() {
#Override
public void handleEvent(Event arg0) {
//Your code here.....
}
});
I have a problem with the focus traversal system in Java. When I tab between components in a pane in my application everything works fine Tab moves the focus to the next component.
Some of my components perform validation on loss of focus, if the validation returns errors then the screens save button is disabled.
My problem occurs when the validated component is followed by the save button.
Tab removes focus from the validated component and begins the asynchronous process of assigning focus to the next component that is enabled (The Save Button)
Next my validation kicks in and disables the save button
The asynchronous process then finished and attempts to assign focus to the now disabled Save button.
The Focus now becomes trapped and tabbing no longer shifts focus because no component actually has the focus.
Has anyone else come across this problem, how did you solve the problem of having the validation and disablement carried out before the focus traversal event started?
You could use an InputVerifier to validate the text field. In this case focus will be placed back on the text field in error.
Or you could change your focus listener to handle this situation. Something like:
FocusListener fl = new FocusAdapter()
{
public void focusLost(final FocusEvent e)
{
JTextField tf = (JTextField)e.getSource();
if (tf.getDocument().getLength() < 1)
{
System.out.println("Error");
button.setEnabled( false );
Component c = e.getOppositeComponent();
if (c instanceof JButton
&& c.isEnabled() == false)
{
tf.requestFocusInWindow();
}
}
else
button.setEnabled( true );
}
};