7

表のセルTableCellRendererに複数のカスタムを使用しています。JFormattedTextFieldと同じ部品を使用していTableCellEditorます。ここで、ユーザーがクリックしたものと、このフィールドのどこを知る必要がありJFormattedTextFieldます (で実行できますviewToModel)。

カスタム を使用する場合、マウス クリックからTableCellEditorを取得する唯一の方法は、 のメソッドです。与えられたのは、親の座標系です。PointisCellEditable(EventObject e)CellEditorPoint

anEvent は、呼び出しコンポーネントの座標系にあります。

しかし、クリックした座標でコンポーネントを取得するにはどうすればよいですか? 試してみまし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,
                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();
            }

        });
    }

}
4

3 に答える 3

10

何がうまくいかないのか完全にはわかりません (オフの場合はお知らせください。これを削除できます:-)

編集の開始をトリガーしたマウス (クリック/プレス) の下の「実際の」コンポーネントを取得したいと仮定すると、エディターがその親に追加された後に (親からエディター座標への) 変換を行うのがコツです。これは shouldSelectCell では保証されていますが、isCellEditable では保証されていません (後者はに呼び出されます) 。

ツリーのコンテキストでの最近の回答(十分に似ているはずです) には、実行可能な例がいくつかあります。関連するスニペットは次のとおりです。

/**
 * 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
            ....
        }
    });
}
于 2011-12-22T11:42:51.770 に答える
1

これはあなたの質問への回答ではなく、表示される結果の説明です。「要求されたポイントに子コンポーネントがないため」がfindComponentAt()返されます。レンダリングを高速化するために使用されるにあります。ここに使用方法の例があります。nullMyCellPanelCellRendererPaneJTable

于 2011-12-22T03:48:59.493 に答える
1

クリックした位置からテーブルの行と列を取得できます。次に、同じレンダラーの getTableCellRendererComponent メソッドを呼び出して、レンダラー コンポーネントを取得します。次に、前の行の高さを y から減算し、前のセルの幅を x から減算してポイントを修正します。次に、レンダリングされたコンポーネントの適切な子を取得します。

于 2011-12-22T05:48:55.217 に答える