java – 使用TableCellEditor时,如何在鼠标单击位置获取组件?

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

使用自定义TableCellEditor时,从鼠标单击获取Point的唯一方法是CellEditor中的isCellEditable(EventObject e)方法.给出的点在父坐标系中.

anEvent is in the invoking component coordinate system.

但是如何在单击的坐标上获取组件?我尝试过findComponentAt(Point p),但它为我返回null.

这是我测试过的一些代码

@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行时).

在使用TableCellEditor和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,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();
            }

        });
    }

}

解决方法

不完全确定我明白出了什么问题(只是让我知道,如果我关闭,所以我可以删除这个:-)

假设您希望获得触发编辑开始的鼠标(单击/按下)下的“真实”组件,诀窍是在将编辑器添加到其父级之后进行转换(从父级到编辑器坐标).这对于s​​houldSelectCell是有保证的,但不是对于isCellEditable(后者之前被调用)

树的上下文中的recent answer(应该足够相似)有一些可运行的示例.这是相关的片段:

/**
 * 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
            ....
        }
    });
}

相关文章

最近看了一下学习资料,感觉进制转换其实还是挺有意思的,尤...
/*HashSet 基本操作 * --set:元素是无序的,存入和取出顺序不...
/*list 基本操作 * * List a=new List(); * 增 * a.add(inde...
/* * 内部类 * */ 1 class OutClass{ 2 //定义外部类的成员变...
集合的操作Iterator、Collection、Set和HashSet关系Iterator...
接口中常量的修饰关键字:public,static,final(常量)函数...