【问题标题】:Java: do file menu clicks take focus?Java:文件菜单点击是否获得焦点?
【发布时间】:2012-01-05 14:30:25
【问题描述】:

我遇到了表格问题,在用户按下 Enter 或 Tab 之前,正在编辑的单元格不会存储其新值,而我希望它在失去焦点后立即提交该值,因为我发现选择“文件” -> 保存'同时编辑单元格导致该单元格的数据丢失。 我发现你可以简单地设置

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

它适用于每次焦点更改,除非选择文件菜单,在这种情况下单元格保持编辑模式。 我的问题是,设置此属性的行为是否与预期的不同,或者默认情况下 Java 中菜单项的焦点是否不同?

【问题讨论】:

    标签: java swing focus jtable


    【解决方案1】:

    如果您不想使菜单项具有焦点,则需要在保存操作中添加如下代码:

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

    【讨论】:

    • 我之前尝试过并得到了一些意想不到的行为,但我又给了它一个不同的方法,现在似乎可以工作了。如果我不能保证我的表只会处理字符串,那会很烦人,但幸运的是它会。我将在下面发布代码。
    【解决方案2】:

    如果您查看 JMenuItem 源代码,就会发现对 initFocusability() 的函数调用会依次调用 setFocusable(false)

    initFocusability() 的 Java 文档

    初始化JMenuItem 的可聚焦性。 JMenuItem 是可聚焦的,但子类可能想要, 这为他们提供了并调用其他东西,或者根本没有。 有关动机,请参阅 {@link javax.swing.JMenu#initFocusability} 这个。

    来自JMenu.JMenu#initFocusability的Java文档

    被重写以不做任何事情。我们希望 JMenu 是可聚焦的,但是 JMenuItem 不想成为,因此我们覆盖它什么都不做。我们不调用 超级的构造函数完成后的 setFocusable(true) JMenu 将被视为可通过 键盘,我们不想要。使组件可被 调用 setFocusable(true) 后的键盘没问题,因为 setFocusable 是 新的 API 并且是这样指定的,但在内部我们不想使用它 像这样我们改变键盘可遍历性。

    听起来您需要致电setFocusable(true);

    【讨论】:

    • 嗯,这听起来不错,但我试过了,但似乎没有帮助。在调用 setFocasable 之前,我还尝试在我的菜单上调用 isFocasable,而且它似乎已经是真的了。
    • 不要因为你在客厅里感到冷而烧床 :-) 或者换句话说:通常,ui 流依赖于菜单/项目只是 临时焦点所有者。不要为了一个未解决的问题而混淆它!
    【解决方案3】:

    我发现上面两个答案的组合已经解决了这个问题。我有一个可聚焦的菜单栏,并添加了一个 DefaultCellEditor 和一个重写的 getTableCellEditorComponent 方法,该方法添加了一个焦点侦听器以停止编辑:

    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;
        }
    });
    

    【讨论】:

    • 不够安全 - 编辑组件甚至可能没有专注于编辑。另外,即使有,如果组件是复合组件(例如 f.i. 组合框),侦听器也将无法触发 通常,当您想要防止编辑的数据丢失时,依赖焦点事件并不是一个好主意:实际焦点围绕编辑的转移往往是非常不确定的。
    • -1 扩展 Kleopatra 的 cmets,只有双击单元格或使用 F2 调用编辑器时,编辑器才会获得焦点。当单元格具有焦点时,没有什么可以阻止用户简单地键入文本。在这种情况下,文本被附加到编辑器中,而编辑器没有获得焦点,因此您的代码将不会被执行。此外,每次调用编辑器时,此代码都会向编辑器组件添加一个新的 FocusListener。
    • 我同意你关于制作多个编辑器的观点 - 这很糟糕。我现在更改了我的代码,这样我就有了自己的编辑器,它扩展了 DefaultCellEditor 并在构造时添加了一个侦听器。至于其他问题,我想他们几乎使该修复变得多余...我尝试通过键入而不是正式调用编辑器来编辑单元格,它似乎仍然可以正常工作,尽管我知道这几乎没有定论并且可以'不代表每个平台上的每个案例。你能提出一个更可靠的方法吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-30
    • 1970-01-01
    相关资源
    最近更新 更多