2011-12-22 23 views
7

テーブルセルにJFormattedTextFieldという複数のカスタムのTableCellRendererを使用します。私はTableCellEditorと同じコンポーネントを使用します。今私はJFormattedTextFieldがクリックされたこと、そしてこのフィールドのどこで(viewToModelでできるか)を知る必要があります。TableCellEditorを使用するとき、どのようにしてマウスクリック位置でコンポーネントを取得できますか?

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

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の行を使用する場合)のためにほぼランダムな値を与える:ここ

は私がテストしたいくつかのコードです。

TableCellEditorTableCellRendererを使用すると、ユーザーがクリックしたコンポーネントを取得するにはどうすればよいですか?


ここでは完全な例である:

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(); 
      } 

     }); 
    } 

} 
+0

+1ですが、希望のフィールド自体を聞くのはなぜですか? – trashgod

+0

@trashgod:セルに既にフォーカスがない限り、 'TableCellEditor'で使用されているときに' MouseEvent'を受け取らない。 'isCellEditable'は、フォーカスを持たない行をクリックしたときに' MouseEvent'を受け取る唯一の方法です。 – Jonas

+0

いいえ、 'MouseEvent'をスキップして、適切な(アクション、プロパティなどの)リスナーを各' JFormattedTextField'に追加することを意味します。 – trashgod

答えて

10

私は(クリックだけで私はオフだ場合、私に知らせて、私は

あなたは、マウスの下に「本物」のコンポーネントを取得したいと仮定すると、この:-)を削除することができます(間違って何が起こっているかを理解し、完全にわかりません/ press)をクリックすると、の後に変換が親からエディタの座標に変換されてになり、エディタがその親に追加されます。それはshouldSelectCell保証だが、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 
      .... 
     } 
    }); 
} 
+1

+1振り返ってみると、 'p3'が_previous_の位置を示していたことがわかります。 – trashgod

+0

@trashgod - 良い見解、それを逃した:-) – kleopatra

+0

@trashgod:ああ、それはそれを説明しています。 – Jonas

1

これは、あなたの質問への答えが、あなたが見る結果の説明ではありません:の子コンポーネントがない」のでfindComponentAt()戻りnull要求されたポイント。 MyCellPanelは、JTableによって使用されるCellRendererPaneにあり、レンダリングのスピードを向上させます。どのように使用されているかの例がありますhere

1

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

+0

しかし、「レンダリングされたコンポーネントの適切な子」を取得するにはどうすればよいですか?この場合には 'findComponentAt()'で取得できません。 – Jonas

+0

独自のfindComponentAtを記述することができます。すべての子を取得し、それぞれに対して境界を取得し、イベントx/y(修正されたもの)が範囲内にあるかどうかをチェックします。 – StanislavL

関連する問題