焦点问题使用JComboBox作为JTable中的单元格编辑器

时间:2021-09-06 22:18:21

I'm having issues with the following code, where I use a JComboBox to change a String value in a table cell. The JComboBox works fine, but if I click in the box and then click away without selecting anything the JComboBox's dropdown remains visible, even if I delete the row. Clicking on another Swing component like a JButton often causes it to go away, but not always.

我遇到以下代码的问题,我使用JComboBox更改表格单元格中的字符串值。 JComboBox工作正常,但是如果我在框中单击然后单击而不选择任何内容,即使我删除了行,JComboBox的下拉列表仍然可见。单击另一个像JButton这样的Swing组件通常会导致它消失,但并非总是如此。


    TableColumn col = myTable.getColumnModel().getColumn(0);
    JComboBox eq = new JComboBox();
    eq.addItem("==");
    eq.addItem("!=");
    DefaultCellEditor editor = new DefaultCellEditor(eq);
    col.setCellEditor(editor);

Edit: I had neglected to mention that earlier I set:

编辑:我之前忽略了提到:


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

If I comment this line out or set it false, then clicking on other Swing components does NOT cause the box to vanish. With it in, clicking on anything that takes focus causes the box to go away, making the problem less annoying but possibly masking the cause of the behavior.

如果我对此行进行注释或将其设置为false,则单击其他Swing组件不会导致该框消失。有了它,点击任何需要聚焦的东西会导致盒子消失,使问题不那么烦人,但可能掩盖了行为的原因。

Am I doing something wrong here, or forgetting a step? Alternately, is there a way to force it to close itself?

我在这里做错了什么,还是忘记了一步?或者,有没有办法迫使它自己关闭?

Thanks!

谢谢!

2 个解决方案

#1


11  

To understand this you'll need to understand what goes on with an editable table. A short bit of theory:

要理解这一点,您需要了解可编辑表格的内容。一点理论:

Every cell has a potential renderer and editor. The renderer just tells the cell how to draw and does not interact with events. The editor however is a component that can interact with events. When an event happens that triggers an edit, the editor component is added on top of the table. When the edit finishes, the component is removed.

每个单元格都有一个潜在的渲染器和编辑器。渲染器只是告诉单元格如何绘制并且不与事件交互。然而,编辑器是可以与事件交互的组件。当发生触发编辑的事件时,编辑器组件将添加到表的顶部。编辑完成后,组件将被删除。

In order to get the component to go away, you'll have to make sure the cell is not still in the "editing" state. This is why terminateEditOnFocusLast causes the JComboBox to vanish. If you want other things to get the box to go, you'll need to probably call removeEditor() in response to certain events, possibly focus, or cell selection.

为了使组件消失,您必须确保单元格仍处于“编辑”状态。这就是terminateEditOnFocusLast导致JComboBox消失的原因。如果你想让其他东西进入,你可能需要调用removeEditor()来响应某些事件,可能是焦点或单元格选择。

To really get a handle on what happens I'd recommend having a quick look at the source code to removeEditor(), editCellAt() etc., and maybe step through once in a debugger. It's possible you've overridden some of the event handling code, or are calling it when you shouldn't. The editor/event handling code in JTable is fairly fragile, and it's quite easy by accident to get calls to happen in the wrong order with funny side effects.

要真正了解发生的情况,我建议您快速查看removeEditor(),editCellAt()等源代码,并在调试器中单步执行一次。您可能已经覆盖了一些事件处理代码,或者在您不应该调用它时调用它。 JTable中的编辑器/事件处理代码相当脆弱,并且通过有趣的副作用将调用以错误的顺序发生是非常容易的。

Also, Java very subtly changed the event and focus behaviour of JTable between versions once, I think it was between 1.4 and 1.5, when the focus handling for swing changed. So the first thing I'd recommend trying is your code with a different Java version. The bug may have been caused by Sun (some of our complicated editor code had to be changed) and if it differs between releases it is easier to report to Sun.

此外,Java在版本之间非常微妙地改变了JTable的事件和焦点行为,我认为它在1.4到1.5之间,当时swing的焦点处理发生了变化。所以我建议尝试的第一件事是你的代码使用不同的Java版本。该错误可能是由Sun引起的(我们的一些复杂的编辑器代码必须更改),如果它在发行版之间有所不同,则向Sun报告更容易。

#2


1  

I know this question is old but for reference here is my solution. I extend the DefaultCellEditor and listen for the JComboBox to be canceled then force the editor to cancel.

我知道这个问题已经过时了,但这里的参考是我的解决方案。我扩展了DefaultCellEditor并监听JComboBox被取消然后强制编辑器取消。

import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;

public class ComboBoxCellEditor extends DefaultCellEditor {

    public ComboBoxCellEditor(JComboBox comboBox) {
        super(comboBox);
        comboBox.addPopupMenuListener(new PopupMenuListener() {

            public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
            }

            public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
            }

            public void popupMenuCanceled(PopupMenuEvent e) {
                cancelCellEditing();
            }
        });
    }
}

Then ...

然后 ...

DefaultCellEditor editor = new ComboBoxCellEditor(combobox);
column.setCellEditor(editor);

#1


11  

To understand this you'll need to understand what goes on with an editable table. A short bit of theory:

要理解这一点,您需要了解可编辑表格的内容。一点理论:

Every cell has a potential renderer and editor. The renderer just tells the cell how to draw and does not interact with events. The editor however is a component that can interact with events. When an event happens that triggers an edit, the editor component is added on top of the table. When the edit finishes, the component is removed.

每个单元格都有一个潜在的渲染器和编辑器。渲染器只是告诉单元格如何绘制并且不与事件交互。然而,编辑器是可以与事件交互的组件。当发生触发编辑的事件时,编辑器组件将添加到表的顶部。编辑完成后,组件将被删除。

In order to get the component to go away, you'll have to make sure the cell is not still in the "editing" state. This is why terminateEditOnFocusLast causes the JComboBox to vanish. If you want other things to get the box to go, you'll need to probably call removeEditor() in response to certain events, possibly focus, or cell selection.

为了使组件消失,您必须确保单元格仍处于“编辑”状态。这就是terminateEditOnFocusLast导致JComboBox消失的原因。如果你想让其他东西进入,你可能需要调用removeEditor()来响应某些事件,可能是焦点或单元格选择。

To really get a handle on what happens I'd recommend having a quick look at the source code to removeEditor(), editCellAt() etc., and maybe step through once in a debugger. It's possible you've overridden some of the event handling code, or are calling it when you shouldn't. The editor/event handling code in JTable is fairly fragile, and it's quite easy by accident to get calls to happen in the wrong order with funny side effects.

要真正了解发生的情况,我建议您快速查看removeEditor(),editCellAt()等源代码,并在调试器中单步执行一次。您可能已经覆盖了一些事件处理代码,或者在您不应该调用它时调用它。 JTable中的编辑器/事件处理代码相当脆弱,并且通过有趣的副作用将调用以错误的顺序发生是非常容易的。

Also, Java very subtly changed the event and focus behaviour of JTable between versions once, I think it was between 1.4 and 1.5, when the focus handling for swing changed. So the first thing I'd recommend trying is your code with a different Java version. The bug may have been caused by Sun (some of our complicated editor code had to be changed) and if it differs between releases it is easier to report to Sun.

此外,Java在版本之间非常微妙地改变了JTable的事件和焦点行为,我认为它在1.4到1.5之间,当时swing的焦点处理发生了变化。所以我建议尝试的第一件事是你的代码使用不同的Java版本。该错误可能是由Sun引起的(我们的一些复杂的编辑器代码必须更改),如果它在发行版之间有所不同,则向Sun报告更容易。

#2


1  

I know this question is old but for reference here is my solution. I extend the DefaultCellEditor and listen for the JComboBox to be canceled then force the editor to cancel.

我知道这个问题已经过时了,但这里的参考是我的解决方案。我扩展了DefaultCellEditor并监听JComboBox被取消然后强制编辑器取消。

import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;

public class ComboBoxCellEditor extends DefaultCellEditor {

    public ComboBoxCellEditor(JComboBox comboBox) {
        super(comboBox);
        comboBox.addPopupMenuListener(new PopupMenuListener() {

            public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
            }

            public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
            }

            public void popupMenuCanceled(PopupMenuEvent e) {
                cancelCellEditing();
            }
        });
    }
}

Then ...

然后 ...

DefaultCellEditor editor = new ComboBoxCellEditor(combobox);
column.setCellEditor(editor);