我有一个单元编辑器,它由JPanel上的多个组件组成。当我的自定义单元格编辑器停止编辑时,表格将失去焦点,而不是将焦点转移到下一个单元格。JTable在使用复合JPanel单元编辑器编辑后失去焦点
下面是一个简单的例子。通过表格键入每个单元格和选项卡。请注意,在访问第三列后,该表将焦点丢到面板上的另一个文本字段。
更新:此问题似乎在Java7中得到解决。该示例必须与Java 6一起运行才能看到焦点丢失的行为。
import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import javax.swing.AbstractCellEditor;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableModel;
import javax.swing.text.JTextComponent;
public class TableEditorFocusExample extends JFrame
{
private JTable m_table;
private TableModel tableModel;
public TableEditorFocusExample()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener()
{
@Override
public void eventDispatched(AWTEvent event)
{
System.out.println("FOCUS " +
event +
"\n source=" +
event.getSource());
}
}, AWTEvent.FOCUS_EVENT_MASK | AWTEvent.WINDOW_FOCUS_EVENT_MASK);
tableModel = new DefaultTableModel(4, 4);
m_table = new JTable(tableModel)
{
@Override
public void changeSelection(
int row,
int column,
boolean toggle,
boolean extend)
{
super.changeSelection(row, column, toggle, extend);
if (editCellAt(row, column))
{
Component editor = getEditorComponent();
editor.requestFocusInWindow();
if (editor instanceof JTextComponent)
{
((JTextComponent)editor).selectAll();
}
}
}
};
m_table.setModel(tableModel);
m_table.setSurrendersFocusOnKeystroke(true);
m_table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE); //$NON-NLS-1$
DefaultCellEditor textFieldCellEditor = new DefaultCellEditor(new JTextField());
textFieldCellEditor.setClickCountToStart(1);
TableCellEditor panelBasedCellEditor = new PanelCellEditor();
m_table.getColumnModel().getColumn(0).setCellEditor(textFieldCellEditor);
m_table.getColumnModel().getColumn(1).setCellEditor(textFieldCellEditor);
m_table.getColumnModel().getColumn(2).setCellEditor(panelBasedCellEditor);
m_table.getColumnModel().getColumn(3).setCellEditor(textFieldCellEditor);
m_table.setColumnSelectionAllowed(true);
final JButton ok = new JButton("reset");
JPanel panel = new JPanel();
panel.add(m_table);
// add a component to grab focus when the table editor loses focus
final JTextField textField = new JTextField(8);
final Color origTextColor = textField.getBackground();
textField.addFocusListener(new FocusAdapter()
{
@Override
public void focusGained(FocusEvent e)
{
System.err.println("focus gained from: " + e.getSource());
textField.setBackground(Color.red);
}
});
// reset the text field background color to the pre-focus color
ok.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
textField.setBackground(origTextColor);
}
});
panel.add(textField);
panel.add(ok);
getContentPane().add(panel);
}
public class PanelCellEditor extends AbstractCellEditor implements
TableCellEditor
{
public PanelCellEditor()
{
m_textfield.setBackground(Color.green);
m_panel = new JPanel(new GridLayout())
{
@Override
public boolean requestFocusInWindow()
{
// when the table transfers focus to the editor,
// forward focus onto the text field.
return m_textfield.requestFocusInWindow();
}
};
m_panel.add(m_textfield);
}
@Override
public Object getCellEditorValue()
{
return m_textfield.getText();
}
@Override
public Component getTableCellEditorComponent(
JTable table,
Object value,
boolean isSelected,
int row,
int column)
{
m_textfield.setText(value == null ? "" : value.toString());
return m_panel;
}
private JPanel m_panel;
private JTextField m_textfield = new JTextField(5);
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
TableEditorFocusExample test = new TableEditorFocusExample();
test.setSize(600, 300);
test.setVisible(true);
}
});
}
}
我发现了一个类似的问题here,但解决的办法似乎是不完整的,因为在自定义编辑器的文本字段不具有焦点,它的光标不显示使它不清楚用户的场可用于文本输入。
任何人都有更好的解决方案?
可能会或可能不相关:编辑实现_invalid_:当编辑停止它必须实现它的听众的通知/取消 – kleopatra
是不是AbstraceCellEditor在stopCellEditing()和cancellCellEditing()中处理通知? – esigler
是的,但这只是故事的一部分(当外部合作者显式调用stop/cancelEditing时)缺少的是编辑器内部 - 编辑器 - 根据用户手势在编辑器(fi当按下Enter键进入复合编辑器的内部文本字段时) – kleopatra