我有一個單元編輯器,它由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