gpt4 book ai didi

java - 使用复合 JPanel 单元格编辑器编辑后 JTable 失去焦点

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:15:13 25 4
gpt4 key购买 nike

我有一个单元格编辑器,它由 JPanel 上的几个组件组成。当我的自定义单元格编辑器停止编辑时,表格会失去焦点,而不是将焦点转移到下一个单元格。

这是一个简单的例子。在表格中的每个单元格和制表符中键入内容。请注意,在访问第 3 列后,表格的焦点将转移到面板上的另一个文本字段。

更新:这个问题似乎在 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 ,但解决方案似乎不完整,因为自定义编辑器上的文本字段没有焦点,它的光标不显示,使用户不清楚该字段是否可用于文本输入。

谁有更好的解决方案?

最佳答案

不错的挖掘 :-)

对于 jdk6,您可以考虑使用 SwingX and its JXTable它解决了这个问题(刚刚检查过,忘记了我们已经解决了一些焦点问题:-)。或者,如果这不是一个选项,请查看其代码并复制重写的 transferFocus(及相关)方法和改进的 EditorRemover。

并且不要忘记让您的编辑器遵守其契约(Contract):

       Action action = new AbstractAction() {

@Override
public void actionPerformed(ActionEvent e) {
stopCellEditing();
}

};
m_textfield.setAction(action);

关于java - 使用复合 JPanel 单元格编辑器编辑后 JTable 失去焦点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7958990/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com