在 JButton 上执行 actionPerformed,因为 TableCellEditor 在 MouseDown 上错误地调用

发布于 2024-12-10 17:23:10 字数 4213 浏览 0 评论 0原文

我正在尝试使用 JButton 作为我的 JTableTableCellRendererTableCellEditor。在我的测试场景中,我有 5 行,每行显示一个 JButton 作为渲染器和编辑器(编辑器和渲染器的不同按钮实例)。当我第一次单击一个按钮时,当我释放鼠标按钮时,将调用编辑器按钮的 actionPerformed 。当我单击另一行中的另一个按钮时,当我按下鼠标按钮(MOUSE_PRESSED)时,编辑器按钮的 actionPerformed 事件已经被调用。这种行为看起来不太对劲。通常,actionPerformed 事件在释放鼠标按钮时调用,而不是在按下鼠标按钮时调用。当随后按下另一行中的另一个按钮时,在释放鼠标按钮时再次正确调用 actionPerformed ,在下一个按钮上单击另一行中的 actionPerformed 再次(错误地)调用MOUSE_DOWN 等等。

将焦点移出表格然后单击按钮时,释放鼠标按钮时会正确调用 actionPerformed。此外,当要单击的按钮所在的行中的表行编辑器首先获得焦点(激活)然后单击按钮时,行为也是正确的。然后,唯一不起作用的情况是当表格单元格编辑器处于活动状态,然后单击另一个表格行中的按钮时。

比较两种情况下调用 actionPerformed 时的堆栈跟踪,我发现在错误的情况下 DefaultKeyboardFocusManager(KeyboardFocusManager).redispatchEventBasicButtonListener.focusLost(FocusEvent) 被调用,这对我来说看起来都很可疑。

这是我的问题的一些演示代码:

import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.AbstractCellEditor;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;

public class TableButtonTest extends JFrame
{

    private JTable  table;

    public TableButtonTest()
    {
        super("TableButtonTest");

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel contentPane = new JPanel(new GridLayout(1, 0));
        contentPane.setOpaque(true);
        setContentPane(contentPane);

        table = new JTable(new MyTableModel());
        table.setPreferredScrollableViewportSize(new Dimension(500, 70));
        add(table);

        setPreferredSize(new Dimension(600, 200));

        TableCellRenderer defaultBtnRenderer = new TableCellRenderer()
        {
            private JButton btn = new JButton("aa");

            public Component getTableCellRendererComponent(JTable _table, Object value,
                boolean isSelected, boolean hasFocus, int row, int column)
            {
                return btn;
            }
        };

        table.getColumnModel().getColumn(0).setCellRenderer(defaultBtnRenderer);
        table.getColumnModel().getColumn(0).setCellEditor(new ButtonEditor());

        pack();
        setVisible(true);

    }

    public class ButtonEditor extends AbstractCellEditor implements TableCellEditor
    {
        private JButton btn = new JButton("bb");
        {
            btn.addActionListener(new ActionListener()
            {

                public void actionPerformed(ActionEvent e)
                {
                    System.out.println("BUTTON EVENT");
                }
            });
        }

        public Component getTableCellEditorComponent(JTable _table, Object value, boolean isSelected,
            int row, int column)
        {
            return btn;
        }

        public Object getCellEditorValue()
        {
            return null;
        }
    }

    class MyTableModel extends AbstractTableModel
    {
        public int getColumnCount()
        {
            return 1;
        }

        public int getRowCount()
        {
            return 5;
        }

        public Object getValueAt(int row, int col)
        {
            return null;
        }

        @Override
        public boolean isCellEditable(int row, int col)
        {
            return true;
        }
    }

    public static void main(String[] args)
    {
        new TableButtonTest();
    }
}

当您启动程序并点击任何“aa”按钮时,它会变成“bb”(表示显示编辑器而不是渲染器)并且当您释放鼠标按钮时“BUTTON EVENT”打印在 STDOUT 上。如果您单击另一行中的另一个按钮,它也会变成“bb”,但在释放鼠标按钮之前“BUTTON EVENT”已打印到 STDOUT。而且按钮文本周围的焦点矩形也不会显示。

我使用 Java 1.6.0_26 和 1.6.0_27 测试了此行为。当我使用 1.5.0_17 时,情况变得更糟:当单击第二个按钮时,没有调用任何 actionPerformed,仅显示“bb”按钮。第三次点击再次正常工作,第四次则无法正常工作,依此类推。因此,与 Java 1.6 的区别在于,在 1.6 上,释放鼠标按钮时会调用第二次(和第四次……)单击 actionPerformed,而在 1.5 上则根本不会调用。

但我不在乎 1.5,我只想它能与 1.6 一起工作。

我该怎么做才能使这项工作成功?

谢谢。

I'm trying to use a JButton as TableCellRenderer and TableCellEditor for my JTable. In my test scenario I have 5 rows which each shows a JButton as Renderer and Editor (different button instances for editor and renderer). When I click on one button for the first time actionPerformed of the editor-button is invoked, when I RELEASE the mouse button. When I click on another button in another row then, the actionPerformed-Event of the editor-button is already invoked, when I put the mouse button down (MOUSE_PRESSED). This behaviour doesn't seem right. Usually the actionPerformed-event is invoked when releasing the mouse button, not when pressing it. When pressing another button in another row afterwards, actionPerformed is again invoked correctly when releasing the mouse button, on the next button click in another row actionPerformed is again (incorrectly) invoked on MOUSE_DOWN and so forth.

When moving the focus out of the table and then clicking on a button, actionPerformed is invoked correctly when releasing the mouse button. Also when the table row editor in the row the button to be clicked is in is first focused (activated) and then the button is clicked, the behaviour also is correct. Then only situation when it doesn't work is when a table cell editor is active and then the button in another table row is clicked.

Comparing the stacktraces when actionPerformed is invoked in both cases I found out that in the incorrect case DefaultKeyboardFocusManager(KeyboardFocusManager).redispatchEvent and BasicButtonListener.focusLost(FocusEvent) are invoked, which both look suspicious to me.

Here is a little demonstration code for my problem:

import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.AbstractCellEditor;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;

public class TableButtonTest extends JFrame
{

    private JTable  table;

    public TableButtonTest()
    {
        super("TableButtonTest");

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel contentPane = new JPanel(new GridLayout(1, 0));
        contentPane.setOpaque(true);
        setContentPane(contentPane);

        table = new JTable(new MyTableModel());
        table.setPreferredScrollableViewportSize(new Dimension(500, 70));
        add(table);

        setPreferredSize(new Dimension(600, 200));

        TableCellRenderer defaultBtnRenderer = new TableCellRenderer()
        {
            private JButton btn = new JButton("aa");

            public Component getTableCellRendererComponent(JTable _table, Object value,
                boolean isSelected, boolean hasFocus, int row, int column)
            {
                return btn;
            }
        };

        table.getColumnModel().getColumn(0).setCellRenderer(defaultBtnRenderer);
        table.getColumnModel().getColumn(0).setCellEditor(new ButtonEditor());

        pack();
        setVisible(true);

    }

    public class ButtonEditor extends AbstractCellEditor implements TableCellEditor
    {
        private JButton btn = new JButton("bb");
        {
            btn.addActionListener(new ActionListener()
            {

                public void actionPerformed(ActionEvent e)
                {
                    System.out.println("BUTTON EVENT");
                }
            });
        }

        public Component getTableCellEditorComponent(JTable _table, Object value, boolean isSelected,
            int row, int column)
        {
            return btn;
        }

        public Object getCellEditorValue()
        {
            return null;
        }
    }

    class MyTableModel extends AbstractTableModel
    {
        public int getColumnCount()
        {
            return 1;
        }

        public int getRowCount()
        {
            return 5;
        }

        public Object getValueAt(int row, int col)
        {
            return null;
        }

        @Override
        public boolean isCellEditable(int row, int col)
        {
            return true;
        }
    }

    public static void main(String[] args)
    {
        new TableButtonTest();
    }
}

When you start the program and hit any of the "aa" buttons, it turns to "bb" (indicating that the editor is shown instead of the renderer) and when you release the mouse button "BUTTON EVENT" is printed on STDOUT. If you click on another button in another row then, it also turns to "bb" but "BUTTON EVENT" is already printed to STDOUT before you release the mouse button. And also the focus rectangle around the button text isn't shown.

I tested this behaviour with Java 1.6.0_26 and 1.6.0_27. When I used 1.5.0_17 it got event worse: When clicking on the second button NO actionPerformed was invoked, only the "bb"-button was shown. The third click then again worked correctly, the fourth didn't and so forth. So the difference to Java 1.6 is, that on 1.6 on the second (and fourth, ...) click actionPerformed is invoked when releasing the mouse button, on 1.5 is isn't invoked at all.

But I dont care about 1.5, I just want it to work with 1.6.

What can I do to make this work?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

转瞬即逝 2024-12-17 17:23:10

表格按钮列显示了我使用按钮作为渲染器/编辑器。

Table Button Column shows my solution for using a button as a renderer/editor.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文