使用TableCellEditor时,如何在鼠标单击位置获得组件? [英] How can I get the component at the mouse click position, when using a TableCellEditor?

查看:65
本文介绍了使用TableCellEditor时,如何在鼠标单击位置获得组件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在表单元格中使用具有多个JFormattedTextField的自定义TableCellRenderer.我使用与TableCellEditor相同的组件.现在,我需要知道用户单击了什么JFormattedTextField以及该字段中的什么位置(可以使用viewToModel完成).

I use a custom TableCellRenderer with multiple JFormattedTextField in the table cells. I use the same component as TableCellEditor. Now I need to know in what JFormattedTextField the user clicked, and also where in this field (can be done with viewToModel).

使用自定义TableCellEditor时,通过鼠标单击获取Point的唯一方法是

When using a custom TableCellEditor, the only way to get the Point from the mouse click is the isCellEditable(EventObject e) method in CellEditor. The Point given is in the parents coordinate system.

anEvent在调用组件坐标系中.

anEvent is in the invoking component coordinate system.

但是如何在单击的坐标处获得组件?我尝试使用 findComponentAt(Point p) ,但它会为我返回null.

But how can I get the component at the clicked coordinate? I have tried with findComponentAt(Point p) but it returns null for me.

以下是我测试过的一些代码:

Here is some code I have tested with:

@Override
    public boolean isCellEditable(EventObject e) {

        if(e instanceof MouseEvent) {
            MouseEvent ev = (MouseEvent)e;
            Point p = ev.getPoint();

            // gives strange values
            Point p3 = editor.getLocation();

            // x: 0 y: 0
            Point tp = ((JTable)e.getSource()).getLocation();

            // these returns null
            Component c1 = renderer.findComponentAt(p);
            Component c2 = editor.findComponentAt(p);

            System.out.println("Click at " + p + " editor at: " + p3);
        }

        return true;
    }

组件位置editor.getLocation();的值几乎给出了y坐标的随机值(例如,在表中使用5行时).

The values for the component's location editor.getLocation(); gives almost random values for the y-coordinate (e.g. when using 5 rows in the table).

在使用TableCellEditorTableCellRenderer时如何获得用户单击的组件?

How can I get the component the user clicked on when using a TableCellEditor and a TableCellRenderer?

这是一个完整的例子:

public class FormattedTableEditDemo extends JFrame {

    public FormattedTableEditDemo() {

        MyTableModel model = new MyTableModel();
        MyTableCellEditorAndRenderer cellEditorAndRenderer =
                new MyTableCellEditorAndRenderer();     

        JTable table = new JTable(model);
        table.setDefaultRenderer(BigDecimal.class, cellEditorAndRenderer);
        table.setDefaultEditor(BigDecimal.class, cellEditorAndRenderer);
        table.setRowHeight(40);

        add(new JScrollPane(table));
        pack();
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);

    }

    class MyTableCellEditorAndRenderer extends AbstractCellEditor
            implements TableCellEditor, TableCellRenderer {

        MyCellPanel editor = new MyCellPanel();
        MyCellPanel renderer = new MyCellPanel();

        @Override
        public Object getCellEditorValue() {
            return editor.getValue();
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, 
                Object value, boolean isSelected, boolean hasFocus,
                int row, int column) {
            renderer.setValue(value);
            return renderer;
        }

        @Override
        public Component getTableCellEditorComponent(JTable table,
                Object value, boolean isSelected, int row, int column) {
            editor.setValue(value);
            return editor;
        }

        @Override
        public boolean shouldSelectCell(EventObject e) {
            return false;
        }

        @Override
        public boolean isCellEditable(EventObject e) {

            if(e instanceof MouseEvent) {
                MouseEvent ev = (MouseEvent)e;
                Point p = ev.getPoint();

                // gives strange values
                Point p3 = editor.getLocation();

                // x: 0 y: 0
                Point tp = ((JTable)e.getSource()).getLocation();

                // these returns null
                Component c1 = renderer.findComponentAt(p);
                Component c2 = editor.findComponentAt(p);

                System.out.println("Click at " + p + " editor at: " + p3);
            }

            return true;
        }

    }

    class MyCellPanel extends JPanel {

        JFormattedTextField field1 = new JFormattedTextField();
        JFormattedTextField field2 = new JFormattedTextField();

        public MyCellPanel() {

            field1.setColumns(8);
            field2.setColumns(8);

            field2.setValue(new BigDecimal("0.00"));

            setLayout(new BorderLayout());
            add(field1, BorderLayout.WEST);
            add(Box.createHorizontalStrut(30));
            add(field2, BorderLayout.EAST);
        }

        public Object getValue() {
            return field1.getValue();
        }

        public void setValue(Object value) {
            field1.setValue(value);
        }
    }

    class MyTableModel extends AbstractTableModel {

        List<BigDecimal> values = new ArrayList<BigDecimal>();

        public MyTableModel() {

            // test values
            values.add(new BigDecimal("37.00"));
            values.add(new BigDecimal("4305.90"));
            values.add(new BigDecimal("386.04"));
            values.add(new BigDecimal("3486.58"));
            values.add(new BigDecimal("6546.45"));
        }

        @Override
        public int getColumnCount() {
            return 1;
        }

        @Override
        public int getRowCount() {
            return values.size();
        }

        @Override
        public Object getValueAt(int row, int column) {
            return values.get(row);
        }

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

        @Override
        public Class<?> getColumnClass(int column) {
            return BigDecimal.class;
        }

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new FormattedTableEditDemo();
            }

        });
    }

}

推荐答案

不完全确定我了解出了什么问题(请让我知道我是否关机,以便删除此:-)

Not entirely sure I understand what's going wrong (just let me know if I'm off, so I can delete this :-)

假设您想在触发编辑开始的鼠标(单击/按下)下获取真实"组件,诀窍是在之后进行转换(从父坐标到编辑器坐标)编辑器将添加到其父级.对于shouldSelectCell,这是有保证的,但对于isCellEditable(后者称为之前),则不能保证

Assuming you want to get the "real" component under the mouse (click/press) which triggered the start of editing, the trick is to do the conversion (from parent to editor coordinates) after the editor is added to its parent. That's guaranteed for shouldSelectCell, but not for isCellEditable (the latter being called before)

一个最新答案在树的上下文中(应该足够相似)有一些可运行的示例.这是相关的代码段:

A recent answer in the context of a tree (should be similar enough) has some runnable example. Here's the relevant snippet:

/**
 * At this point in time the editing component is added to the table (not documented!) but
 * table's internal cleanup might not yet be ready
 */ 
@Override
public boolean shouldSelectCell(EventObject anEvent) {
    if (anEvent instanceof MouseEvent) {
        redirect((MouseEvent) anEvent);
    }
    return false;
}

private void redirect(final MouseEvent anEvent) {
    SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
            MouseEvent ev = SwingUtilities.convertMouseEvent(anEvent.getComponent(), anEvent, editor);
            // at this point you have the mouse coordinates in the editor's system
            // do stuff, like f.i. findComponent
            ....
        }
    });
}

这篇关于使用TableCellEditor时,如何在鼠标单击位置获得组件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆