使用TableCellEditor时,如何在鼠标单击位置获得组件? [英] How can I get the component at the mouse click position, when using a TableCellEditor?
问题描述
我在表单元格中使用具有多个JFormattedTextField
的自定义TableCellRenderer
.我使用与TableCellEditor
相同的组件.现在,我需要知道用户单击了什么JFormattedTextField
以及该字段中的什么位置(可以使用viewToModel
完成).
I use a custom TableCellRenderer
with multiple JFormattedTextField
in the table cells. I use the same component as TableCellEditor
. Now I need to know in what JFormattedTextField
the user clicked, and also where in this field (can be done with viewToModel
).
使用自定义TableCellEditor
时,通过鼠标单击获取Point
的唯一方法是
When using a custom TableCellEditor
, the only way to get the Point
from the mouse click is the isCellEditable(EventObject e)
method in CellEditor
. The Point
given is in the parents coordinate system.
anEvent在调用组件坐标系中.
anEvent is in the invoking component coordinate system.
但是如何在单击的坐标处获得组件?我尝试使用 findComponentAt(Point p)
,但它会为我返回null
.
But how can I get the component at the clicked coordinate? I have tried with findComponentAt(Point p)
but it returns null
for me.
以下是我测试过的一些代码:
Here is some code I have tested with:
@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行时).
The values for the component's location editor.getLocation();
gives almost random values for the y-coordinate (e.g. when using 5 rows in the table).
在使用TableCellEditor
和TableCellRenderer
时如何获得用户单击的组件?
How can I get the component the user clicked on when using a TableCellEditor
and a 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();
}
});
}
}
推荐答案
不完全确定我了解出了什么问题(请让我知道我是否关机,以便删除此:-)
Not entirely sure I understand what's going wrong (just let me know if I'm off, so I can delete this :-)
假设您想在触发编辑开始的鼠标(单击/按下)下获取真实"组件,诀窍是在之后进行转换(从父坐标到编辑器坐标)编辑器将添加到其父级.对于shouldSelectCell,这是有保证的,但对于isCellEditable(后者称为之前),则不能保证
Assuming you want to get the "real" component under the mouse (click/press) which triggered the start of editing, the trick is to do the conversion (from parent to editor coordinates) after the editor is added to its parent. That's guaranteed for shouldSelectCell, but not for isCellEditable (the latter being called before)
一个最新答案在树的上下文中(应该足够相似)有一些可运行的示例.这是相关的代码段:
A recent answer in the context of a tree (should be similar enough) has some runnable example. Here's the relevant snippet:
/**
* 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
....
}
});
}
这篇关于使用TableCellEditor时,如何在鼠标单击位置获得组件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!