简体   繁体   中英

Java: do file menu clicks take focus?

I had a problem with tables whereby a cell being edited did not store its new value until the user pressed enter or tab, whereas I wanted it to commit the value as soon as focus was lost as I was finding that selecting 'file -> save' whilst editing a cell caused that cell's data to be lost. I found that you can simply set

table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);

which works well for every change of focus except when the file menu is selected, in which case the cell stays in edit mode. My question is, does setting this property not behave as one might expect it to, or does focus work differently for menu items by default in Java?

If you don't want to make the menu items focusable then you will need to add code like the following in your Save Action:

if (table.isEditing())
    table.getCellEditor().stopCellEditing();

If you look at the JMenuItem source code there is a function call being made to initFocusability() witch in turns calls setFocusable(false) .

Java Doc for initFocusability()

Inititalizes the focusability of the the JMenuItem . JMenuItem 's are focusable, but subclasses may want to be, this provides them the and invoke something else, or nothing at all. Refer to {@link javax.swing.JMenu#initFocusability} for the motivation of this.

Java Doc from JMenu.JMenu#initFocusability

Overriden to do nothing. We want JMenu to be focusable, but JMenuItem doesn't want to be, thus we override this do nothing. We don't invoke setFocusable(true) after super's constructor has completed as this has the side effect that JMenu will be considered traversable via the keyboard, which we don't want. Making a Component traversable by the keyboard after invoking setFocusable(true) is OK, as setFocusable is new API and is speced as such, but internally we don't want to use it like this else we change the keyboard traversability.

So it sounds like you need to call setFocusable(true); .

I have found that a combination of the two answers above has solved this problem. I have a focusable menu bar, and have added a DefaultCellEditor with an overridden getTableCellEditorComponent method that adds a focus listener to stop editing:

table.setDefaultEditor(String.class, new DefaultCellEditor(new JTextField()){
@Override
public Component getTableCellEditorComponent(JTable table, Object value,
             boolean isSelected,
             int row, int column)
{
    Component c = super.getTableCellEditorComponent(table, value, isSelected, row, column);
    c.addFocusListener(new FocusListener()
    {
        public void focusGained(FocusEvent e)
        {
        }
        public void focusLost(FocusEvent e)
        {
            stopCellEditing();
        }
    });
    return c;
    }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM