I have a JTable with a custom cell editor. The editor implements FocusListener so I can check if the cell's contents is valid if the user clicks away from the cell.
I'd like to use a JOptionPane within focusLost (in the EventDispatchThread) to allow the user to select whether to revert to an old value or accept an adjusted value.
Here's the problem; if the user is editing a cell, then clicks a button away from the table, the button's actionlisteners are alerted before JOptionPane has returned.
This is what I'd like to happen:
User edits cell
User clicks button
Cell detects focus lost
JOptionPane displayed and user selects action
JOptionPane closes and cell's value set
Button's actionListeners called
Instead, this is happening:
User edits cell
User clicks button
Cell detects focus lost
JOptionPane displayed and user selects action
Button's actionListeners called
JOptionPane closes and cell's value set
Is it possible to postpone the button's action events until after the JOptionPane has closed?
From other threads, I've read that JDialog does some magic to ensure event dispatching continues so the Dialog itself can handle events.
From what I gather, you don't want the button's action-listener to activate at all, until AFTER the user selects the correct value from the JOptionPane.
To me it seems like the solution would be to set up a 'disabled' flag which goes up once the focusLost is triggered. Once the selection is made, the disabled flag goes down. When the button action is triggered, it checks if the form is disabled; if it is, it does nothing. If it isn't it continues as normal.
Notice the button event won't go automatically once the user selected something in the JOptionPane, but instead he will have to click the button again. To me this seems like better functionality then having the button 'clicked' again for him after he is required to change the form.
Put your validation logic inside TableCellEditor#stopCellEditing(), showing your dialog and returning false if the value is not valid.
To automatically stop table editing on focus lost, use table.putClientProperty("terminateEditOnFocusLost", true);, but I don't think that will stop the buttons action listener from running. Instead I usually stop the table edit in the actionPerformed and do nothing when false is returned (or cancel editing when appropriate, for example if the action is to delete that table row).
Related
In my JavaFX application I need to detect when the user canceled a drag action (like right clicking while dragging or pressing ESC button while dragging). I tried to listen on every DragEvent type on my main window, like DRAG_EXITED_TARGET or DRAG_EXITED but those are fired even if the cursor moves to another Node... I'm unable to narrow it to the single event of canceling the drag action.
I read that event.getGestureTarget() == null could mean that the user canceled the action, but it's also null when it leaves to another Node.
I managed to get this working for me by adding a PropertyChangeListener to a window's focusedProperty. When the user cancels the drag action, my window is losing the focus so this works for me.
I have an application in which there is a textbox and a button. the textbox has focusListener(for incorrect values) and the button has actionListener(for saving the value into a file).
An error message window pops up when a wrong value is entered in the textfield as soon as it loses focus. Now I have 2 senarios.
when the focus is lost from tab out and if a wrong value is entered in the field then the pop up window shows up correctly.
But when i enter a wrong value in the field and without tab out I click the button then the actionListener is activated before the focusListener(Focus Lost) and it saves the wrong value in the text file and then shows the error message.
How should I stop the incorrect value to be saved into file by running the focuslistener first?
ActionListener running before focus listener
Focus, FocusListener, Focus Subsystem is asyncronous, you can sheduling those events, but can caused another side effects, I'd suggest don't do that
delay required events in EDT by using invokeLater,
I have a JComboBox with multiple values in it. I need to be able to detect when the user clicks the JComboBox but does not change the currently selected item.
Neither itemStateChanged nor actionPerformed fire when this happens.
What event should I be using?
How about recording the combo box's state when the mouse button is pressed, and comparing it to the value the box has when the mouse button is released?
attach a MouseListener to the JComboBox
override the mousePressed() method to record the box's state to a temp variable
override the mouseReleased() method to compare the box's value to the temp variable's value
At this point, it's a simple equality check.
Add a MouseListener to the JComboBox using its addMouseListener method. You will want to extend MouseAdapter and override only the mouseClicked method.
What if the user users the keyboard to open the popup and then uses the escape key to close the popup?
I would use a PopupMenuListener. This should handle both mouse and keyboard actions. The concept would be the same as other suggestions. When the popup is displayed you save the selected index. When is closes you compare the selected index to see it it has changed.
I was looking specifically at right mouse click on items, so it's a slightly different problem.
But the solution for me was to
Subclass JComboBox substituting getCellRenderer() with a subclassed DefaultListCellRenderer.
In the cell renderer intercept getListCellRendererComponent() which has boolean isSelected, boolean cellHasFocus parameters and can be used to watch for mouse events and do list.setToolTipText().
I'm sure the non-final selection change will get there, where it can be intercepted.
Here is the scenario. I have an swing applet with tons of checkboxes. some of them are disabled/unchecked when checking another. Each ItemStateChange() event executes a method to parse the entire form for changes. Is there a way to tell if an ItemStateChange() event was triggered due to a mouse click or from a setSelected() call?
The ItemStateChange() for each checkbox has the standard parameter java.awt.event.ItemEvent evt
I'd like to only call the processOrder() method once when a box is clicked. Right now it fires for each change thats made, regardless of whether the change happened from setSelected(). Sometimes there are 10+ parseForm(); calls from a single click.
You can't tell whether the source of the event is a mouse click or a setSelected call from the ItemEvent.
It sounds like you have a loop in your check box logic. You might want to add a controller that handles the events and sets each checkbox yet ignores events that occur due to calling setSelected on other check boxes.
Is there a way to tell if an ItemStateChange() event was triggered due to a mouse click or from a setSelected() call?
If your application manually invokes the setSelected() method then you can use code like:
checkBox.removeItemListener(...);
checkBox.setSelected(...);
checkBox.addItemListener(...);
If you are able to change to use a MouseListener instead of an ItemListener and respond to the mouseClicked() event you will only receive the events for the checkbox selected by the user.
In my JTable I have a number of actions that can accessed via popup menu or by selecting the configured shortcut. Selecting the action from the popup using mouse or keyboard is fine, and I can use the cursor keys to move to a field next to the original selection no problem. However if I use the shortcutkey instead it performs the action okay but I cannnot exit the selected fields afterwards using the cursor keys, because for some reason the focus is now with a component outside of the JTable.
EDIT:When I start the task I change the cursor and disable the JTable, when I complete the task I renable the table and reset the cursor. If I remove the disable code it works, but this then allow the user to make changes to the table which I dont want, and I cannot understand why it only fails when using keyboard shortcut.
Fixed the problem, after renabling the Jtable I needed to call requestFocusInWindow()