How to disable F10 default action in window (show window menu)? - java

The default action of F10 is to show the menu of the window.
However, I would like to disable this feature.
UPDATED:
Background: I would like to implement a special behavior in a JTextField if the user presses any key. Unfortunately, the JTextField don't get the event when F10 is pressed because it is catched by the window (and the menu is shown).
Does anyone know how to disable this key binding in the window?
I tried to disable it in the root pane but without success:
frame.getRootPane().getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_F10, 0), "none");
I searched a lot but found no solution for this issue. Maybe one of you knows an answer.
UPDATE2
Here a code example to reproduce this behavior:
public static void main(final String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame.setDefaultLookAndFeelDecorated(true);
final JTextField edit = new JTextField();
edit.setEditable(false);
edit.addKeyListener(new KeyAdapter() {
#Override
public void keyReleased(final KeyEvent ke) {
edit.setText(KeyEvent.getKeyText(ke.getKeyCode()));
}
});
final JFrame frame = new JFrame("DEMO");
frame.setSize(320, 240);
frame.getContentPane().add(edit);
frame.setVisible(true);
}
});
}
Plase note: There is a different behavior according to whether "setDefaultLookAndFeelDecorated" is set to true or false.
Thanks in advance :)

I tried to disable it in the root pane but without success:
Check out Key Bindings for the bindings of all Swing components.
You will see that the F10 key is bound to the JMenuBar. So you should be able to use:
menuBar.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_F10, 0), "none");
Edit:
Missed the point that you didn't have a menu bar.
It appears you can't just set the binding to "none". Looks like Swing is still searching up the tree to find an Action to execute. You need to provide a dummy Action that does nothing:
Action action = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
System.out.println("do nothing");
}
};
JPanel content = (JPanel)frame.getContentPane();
String key = "F10";
KeyStroke f10 = KeyStroke.getKeyStroke( key );
frame.getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(f10, key);
frame.getRootPane().getActionMap().put(key, action);

If I did undertand you correctly , Create Keypressed event for your JTextField on netbeans put to following code
private void jTextField1KeyPressed(java.awt.event.KeyEvent evt) {
// Add below
int key = evt.getKeyCode();
if (evt.getSource() == jTextField1)
{
if (key == KeyEvent.VK_F10)
{
// your actions here
System.out.println("Hello I am f10");
}
}
// end of if
}

Related

How can I set a Component focused whenever the JFrame is focused (e.g. by clicking or with Alt+Tab)?

I want to have a JFrame. When it's focused (by clicking on it with the mouse, used with Alt+Tab, or somehow else - like by doing it in the program with it's own methods) a specific Component shall be focused directly.
In my Case it would be the following:
Clicked on JFrame -> JTextField is focused and the user can write in it directly.
Greets, JC
Use a WindowFocusListener and requestFocusInWindow.
myFrame.addWindowFocusListener(new WindowAdapter() {
#Override
public void windowGainedFocus(WindowEvent event) {
someTextField.requestFocusInWindow();
}
});
From https://stackoverflow.com/a/6723316/15093679, you can do:
in = new JTextField(40);
f.addWindowListener( new WindowAdapter() {
public void windowOpened( WindowEvent e ){
in.requestFocus();
}
});
Where f is your JFrame and in is your JTextField.
Hope this works.

How to make Enter key and Submit button have same ActionEvent?

So I have a Submit button with an ActionEvent that consists of around 50 lines of code. How would I assign the exact same ActionEvent for the JFrame as the Submit button whenever it detects the Enter key being pressed? This is what my Submit button's ActionEvent looks like
btnSubmit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// miscellaneous code that needs to be repeated for 'Enter' key press
}
});
What and where would the code for giving the JFrame the same ActionEvent as the Submit button go?
Start by taking a look at How to Use Root Panes and in particular JRootPane#setDefaultButton
When you have components which may consume the Enter key (like text fields), you might need to consider using the key bindings API
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "Enter.pressed");
am.put("Enter.pressed", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
btnSubmit.doClick();
}
});
Now, about now, I might consider making an Action which be applied to both the JButton and key binding
Have a look at How to Use Key Bindings and How to Use Actions for more details
I don't know if there's a more correct swing way, but this should do the trick:
ActionListener listener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
//...
}
}
btnSubmit.addActionListener(listener);
btnEnter.addActionListener(listener);
One way to do this is to use the .doClick() method on the Submit button and create a KeyAdapter:
KeyAdapter Enter = new KeyAdapter(){
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_ENTER){
btnSubmit.doClick();
}
}
};
txtField1.addKeyListener(Enter);
txtField2.addKeyListener(Enter);

Disable a Key Entirely Temporarily with Corresponding Button Java

I have a program that, put in short, advances upon the pressing of a button. During certain execution phases the button is temporarily deactivated to prevent it from firing in code at the wrong point in time. I have now created some Key Bindings to act as shortcuts for the pressing of the buttons, but need to disable them during the same aforementioned times, or else they will cause my array to be trashed and wiped before I even use it.
Any tips, methods, or Java methods I can use to [very] easily but a hold via disablement?
Have the bound key press the JButton with doClick(). Then when the button needs to be deactivated, call setEnabled(false) on the button.
As an aside, I suppose your button and key binding could share the same action, but I don't know if calling setEnabled(false) on the Action will prevent the key from running the Action's actionPerformed method. Time to test.... Be right back...
Edit: yep you can just have the JButton and the bound key share the same Action that is enabled/disabled:
import java.awt.event.*;
import javax.swing.*;
public class TestBoundAbstractActions {
public static void main(String[] args) {
final MyAction myAction = new MyAction();
final JButton actionButton = new JButton(myAction);
JRadioButton enableRadioButton = new JRadioButton("Enabled", true);
enableRadioButton.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
myAction.setEnabled(e.getStateChange() == ItemEvent.SELECTED);
}
});
JPanel panel = new JPanel();
int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
String mKey = "m key";
panel.getInputMap(condition).put(KeyStroke.getKeyStroke(KeyEvent.VK_M, 0), mKey);
panel.getActionMap().put(mKey, myAction);
panel.add(new JLabel("Press \"m\" to activate key-bound action"));
panel.add(actionButton);
panel.add(enableRadioButton);
JOptionPane.showMessageDialog(null, panel);
}
}
class MyAction extends AbstractAction {
public MyAction() {
super("My Action");
putValue(MNEMONIC_KEY, KeyEvent.VK_M);
}
#Override
public void actionPerformed(ActionEvent arg0) {
System.out.println("boo!");
}
}

How to wait for radio button to get selected in lost focus event

I have a Swing program that does a search based on the contents of some text fields and settings of a pair of radio buttons (in a button group). The program will automatically search when certain of the text fields lose focus. The problem comes in when the lose focus event is triggered by a click on one of the radio buttons. The lost focus event on the text field is getting processed before the radio button isSelected() values have changed, so the search is done with the "wrong" (i.e. old) parameters, instead of the parameters based on the new setting of the radio buttons.
I tried invoking the search using my own invokeWhenIdle method (shown below) to run the search after the event queue had settled down, but it still is using the old setting of the radio buttons.
My only working solution is to delay for 250 milliseconds in the lost focus event before running the search, so that the radio buttons have time to change. This works, but it makes the UI seem sluggish.
Any better ideas?
public static void invokeWhenIdle(final int a_max_retry, final Runnable a_runnable) {
if (a_max_retry <= 0) {
throw new IllegalStateException("invokeWhenIdle: Could not run " + a_runnable);
}
// get the next event on the queue
EventQueue l_queue = Toolkit.getDefaultToolkit().getSystemEventQueue();
AWTEvent l_evt = l_queue.peekEvent();
if (l_evt == null) {
// nothing left on the queue (but us), we can do it
SwingUtilities.invokeLater(a_runnable);
} else {
// still something in the queue, try again
SwingUtilities.invokeLater(new Runnable() {
public void run() {
invokeWhenIdle(a_max_retry - 1, a_runnable);
}
});
}
}
Not an answer, but an explanation about what is happening. Maybe it will spark an idea...
The problem is that a mousePressed arms the button model and the mouseReleased actually changes the selected value of the model.
When you execute the FocusListener code the radio button the model is in an undefined state. Even if you add the FocusListener code to the end of the EDT by using invokeLater the code will still execute before the mouseReleased event is generated.
The following shows how you might code the listener to handle this. It assumes the state of the button is about to change:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class FocusSSCCE extends JPanel
{
public FocusSSCCE()
{
final JRadioButton radio = new JRadioButton("Radio");
add( radio );
radio.setMnemonic('R');
JTextField textField = new JTextField(10);
add( textField );
JButton button = new JButton("Button");
add( button );
textField.addFocusListener( new FocusAdapter()
{
public void focusLost(FocusEvent e)
{
boolean isSelected = radio.isSelected();
// Assumes selected state will change
if (radio.getModel().isArmed())
isSelected = !isSelected;
System.out.println( isSelected );
}
});
}
private static void createAndShowUI()
{
JFrame frame = new JFrame("FocusSSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new FocusSSCCE() );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
However, even this approach can't be guaranteed to work. If for some reason the user generates the mousePressed event on the radio button and them moves the mouse away from the radio button before releasing the mouse, then the selected state of the radio button is not changed.
Similiarly, even your original implementation to sleep for 250ms can not be guaranteed to work because the user could theoretically hold down the mouse for more than 250ms which would also generate the wrong value.
My workaround for this was to make the radio buttons non focusable
I can't think of any better approach.
Edit:
I just thought of a wild solution.
textField.addFocusListener( new FocusAdapter()
{
public void focusLost(FocusEvent e)
{
if (e.getOppositeComponent() instanceof JRadioButton)
{
final JRadioButton radio = (JRadioButton)e.getOppositeComponent();
MouseListener ml = new MouseAdapter()
{
public void mouseReleased(MouseEvent e)
{
System.out.println( radio.isSelected() );
radio.removeMouseListener(this);
}
};
radio.addMouseListener( ml );
}
else
System.out.println( radio.isSelected() );
}
});
Basically your processing code won't execute until the mouse has been released when you click on the radio button.

Swing: detect Enter in JComboBox?

I've tried using getInputMap() + getActionMap() on a JComboBox and it seems to have no effect.
I've tried addActionListener() / addItemListener() on a JComboBox and I can't seem to distinguish a change of selection from someone pressing the Return/Enter key.
Any suggestions? In my application, I want the Return/Enter key to be stronger than just selecting, it's a selecting + applying action.
Here's my code to setup the key binding. It works fine (e.g. note("hit ENTER") is called) when component is a JList, but doesn't work when component is a JComboBox.
private void setupApplyProfile(final JComponent component, final MyComboBoxModel mcbm)
{
String enterAction = "applyItem";
KeyStroke enterKey = KeyStroke.getKeyStroke("ENTER");
component.getInputMap().put(enterKey, enterAction);
component.getActionMap().put(enterAction, new AbstractAction()
{
#Override public void actionPerformed(ActionEvent e) {
note("hit ENTER");
applySelectedProfile(mcbm);
}
});
}
Aha, this seems to work: note("cb editor action") gets called when I hit Enter in the combo box field.
comboBox.getEditor().addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent arg0) {
note("cb editor action");
}
});
In my application, I want the Return/Enter key to be stronger than just selecting, it's a selecting + applying action.
If I understand the question you can use the following:
comboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
The ActionEvent and ItemEvents will only be fired when an item is selected from the drop down list when you use the mouse or the enter key. The eEvents will not be fired if you navigate the drop down list using the up/down arrow keys.

Categories