Java:文件菜单的点击会获得焦点吗?

3
我曾经遇到一个表格问题,即当用户编辑单元格时,如果用户没有按下Enter或Tab键,该单元格不会存储其新值,而我希望在失去焦点时立即提交该值,因为我发现在编辑单元格时选择“文件 -> 保存”会导致该单元格的数据丢失。我发现您可以简单地设置,这对于除选择文件菜单之外的每次焦点更改都有效,但在选择文件菜单时,单元格仍处于编辑模式。我的问题是,设置此属性是否不能像人们期望的那样运行,还是默认情况下Java中的菜单项焦点工作方式不同?
3个回答

2
如果您不想使菜单项具有焦点,则需要在“保存”操作中添加以下代码:
if (table.isEditing())
    table.getCellEditor().stopCellEditing();

我之前尝试过那个方法,但得到了一些意外的行为,不过我用另一种方式再试了一次,现在似乎可以工作了。如果我不能保证我的表格只处理字符串,那将很烦人,但幸运的是,它确实是这样的。我会在下面发布代码。 - user1111284

1
如果您查看JMenuItem源代码,会发现调用了initFocusability()函数,该函数又调用了setFocusable(false)函数。
initFocusability()的Java Doc如下:

初始化JMenuItem的可聚焦性。 JMenuItem是可聚焦的,但子类可能希望是,这为它们提供了功能, 并调用其他内容或不调用任何内容。 有关此内容的动机,请参阅{@link javax.swing.JMenu#initFocusability}。

来自JMenu.JMenu#initFocusability的Java Doc。
重写为什么都不做。我们希望JMenu是可聚焦的,但JMenuItem不想要,因此我们重写了这个方法。我们不会在super的构造函数完成后调用setFocusable(true),因为这会导致JMenu被认为是可通过键盘遍历的,而我们不想要这样。在调用setFocusable(true)之后使组件可通过键盘遍历是可以的,因为setFocusable是新的API,并且已经规定了这样的用法,但在内部我们不想这样使用它,否则我们会改变键盘遍历性能。

所以听起来你需要调用setFocusable(true);


嗯,这听起来很对,但是我尝试过了,似乎没有帮助。在调用setFocasable之前,我还尝试了在菜单上调用isFocasable,看起来它本来就是true的。 - user1111284
1
不要因为在客厅感到冷而烧毁卧室床 :-) 换句话说,通常 UI 流程依赖于菜单/项目仅是临时的焦点所有者。不要为了一个未解决的问题而混淆这一点! - kleopatra

-1
我发现结合上述两个答案解决了这个问题。我有一个可聚焦的菜单栏,并添加了一个带有重写的getTableCellEditorComponent方法的DefaultCellEditor,该方法添加了一个焦点监听器以停止编辑:
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;
    }
});

1
不够安全-编辑组件甚至可能没有编辑焦点。即使有焦点,如果组件是复合组件(如comboBox),监听器也将无法触发。通常,在想要防止编辑数据丢失时依赖焦点事件并不是一个好主意:实际焦点转移周围的编辑往往相当不确定。 - kleopatra
-1 在 Kleopatra 的评论基础上,只有在双击单元格或使用 F2 调用编辑器时,编辑器才会获得焦点。如果用户只是在单元格具有焦点时键入文本,则没有任何阻止用户的措施。在这种情况下,文本将附加到编辑器中,而不会使编辑器获得焦点,因此您的代码将不会被执行。此外,每次调用编辑器时,此代码都将向编辑器组件添加新的 FocusListener。 - camickr
我理解你的观点,制作多个编辑器是不好的。现在我已经改变了我的代码,我有了自己的编辑器,它扩展了DefaultCellEditor并在构造时添加了一个监听器。 至于其他问题,它们几乎使得这个修复变得多余了...我尝试通过直接输入而不是正式调用编辑器来编辑单元格,它似乎仍然可以正常工作,虽然我知道这并不能代表每种情况在每个平台上的情况。你能否建议一种更可靠的方法来解决这个问题? - user1111284

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接