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 TableCellEditor
và TableCellRenderer
?
Đâ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();
}
});
}
}
+1 cho sscce, nhưng tại sao không nghe chính trường mong muốn? – trashgod
@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
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