2011-12-22 48 views
7

Tôi sử dụng tùy chỉnh TableCellRenderer với nhiều JFormattedTextField trong các ô trong bảng. Tôi sử dụng cùng một thành phần như TableCellEditor. Bây giờ tôi cần phải biết trong những gì JFormattedTextField người dùng nhấp vào, và cũng là nơi trong lĩnh vực này (có thể được thực hiện với viewToModel).Làm cách nào để lấy thành phần ở vị trí nhấp chuột khi sử dụng TableCellEditor?

Khi sử dụng tùy chỉnh TableCellEditor, cách duy nhất để có được Point từ nhấp chuột là phương pháp isCellEditable(EventObject e) trong CellEditor. Số Point được đưa ra là trong hệ thống tọa độ của phụ huynh.

anEvent nằm trong hệ tọa độ thành phần gọi.

Nhưng làm cách nào tôi có thể nhận thành phần ở tọa độ được nhấp? Tôi đã thử với findComponentAt(Point p) nhưng nó trả về null cho tôi.

Dưới đây là một số mã tôi đã thử nghiệm với:

@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; 
    } 

Các giá trị cho vị trí của thành phần editor.getLocation(); cho giá trị gần như ngẫu nhiên cho y phối hợp (ví dụ khi sử dụng 5 dòng trong bảng).

Làm cách nào để có được thành phần mà người dùng đã nhấp vào khi sử dụng TableCellEditorTableCellRenderer?


Đây là một ví dụ đầy đủ:

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 cho sscce, nhưng tại sao không nghe chính trường mong muốn? – trashgod

+0

@trashgod: Nó không nhận được 'MouseEvent' khi nó được sử dụng trong' TableCellEditor' trừ khi ô đã có tiêu điểm. 'isCellEditable' là cách duy nhất tôi có thể nhận' MouseEvent' khi nhấp vào một hàng không có tiêu điểm. – Jonas

+0

Không, ý tôi là bỏ qua 'MouseEvent' hoàn toàn và thêm một trình lắng nghe thích hợp (hành động, thuộc tính, vv) vào mỗi' JFormattedTextField'. – trashgod

Trả lời

10

Không hoàn toàn chắc chắn tôi hiểu những gì đang xảy ra sai (chỉ cần cho tôi biết nếu tôi đi, để tôi có thể xóa :-) này

Giả sử bạn muốn để có được những "thực" thành phần theo chuột (nhấp chuột/báo chí) đã kích hoạt bắt đầu chỉnh sửa, mẹo là thực hiện chuyển đổi (từ bố cục gốc sang tọa độ biên tập) sau trình chỉnh sửa được thêm vào cha mẹ của nó. Đó là bảo đảm cho shouldSelectCell, nhưng không phải cho isCellEditable (những con người sau gọi là trước)

Một recent answer trong bối cảnh của một cây (nên là đủ tương tự) có một số ví dụ Runnable. Dưới đây là đoạn mã có liên quan:

/** 
* 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 Khi nhìn lại, người ta có thể thấy rằng 'p3' đang hiển thị vị trí _previous_. – trashgod

+0

@trashgod - quan sát tốt, bỏ qua :-) – kleopatra

+0

@trashgod: ah, điều đó giải thích nó. – Jonas

1

Đây không phải là một câu trả lời cho câu hỏi của bạn, nhưng một lời giải thích của kết quả bạn thấy: findComponentAt() lợi nhuận null vì "không có thành phần trẻ em tại điểm được yêu cầu. " MyCellPanel nằm trên CellRendererPane được sử dụng bởi JTable để hiển thị tốc độ. Có một ví dụ về cách nó được sử dụng here.

1

Bạn có thể nhận hàng và cột của bảng từ điểm được nhấp. Sau đó gọi phương thức getTableCellRendererComponent của trình kết xuất đồ họa tương tự để lấy thành phần trình kết xuất. Sau đó, điểm chính xác trừ chiều cao của hàng trước đó từ độ rộng của các ô y và các ô trước đó khỏi x. Sau đó, có được con thích hợp của thành phần kết xuất.

+0

Nhưng làm cách nào để có được "con phù hợp của thành phần được hiển thị"? Tôi không thể có được nó với 'findComponentAt()' trong trường hợp này. – Jonas

+0

Bạn có thể viết findComponentAt riêng. Có được tất cả trẻ em và cho mỗi người trong số họ có được giới hạn và kiểm tra xem sự kiện x/y (sửa chữa những người thân) đang ở trong giới hạn. – StanislavL

Các vấn đề liên quan