我们需要一个用于 JTable
的 CellEditor
来编辑大型多行文本。
我们尝试使用弹出窗口在视觉上扩展 TableCell
,该弹出窗口与右侧和底部的单元格重叠。如果单元格位于右下角、靠近屏幕边界等,这会导致各种问题。
然后我们决定使用模态 JDialog
来编辑单元格值。因此用户可以移动对话框,我们可以保留它的大小和位置。
现在问题开始了;-)
我们无法将第一个输入的字符“转发”到对话框。
关于堆栈溢出的例子有很多,其中直接显示在表格(单元格)中的自定义CellEditor
解决了这个问题,例如:Losing first character in JTable panel based cell editor
以下 SSCCE(来自 camickrs 答案: https://stackoverflow.com/a/3591230/361227 )显示第二个 TableColumn 中的第一次击键大部分时间都会丢失。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Frame;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
/**
* Example taken from this answer: https://stackoverflow.com/a/3591230/361227
*
* @author camickr
*/
public class TablePopupEditor extends DefaultCellEditor
{
private PopupDialog popup;
private String currentText = "";
private JButton editorComponent1;
public TablePopupEditor()
{
super( new JTextField() );
setClickCountToStart( 2 );
// Use a JButton as the editor component
editorComponent1 = new JButton();
editorComponent1.setBackground( Color.white );
editorComponent1.setBorderPainted( false );
editorComponent1.setContentAreaFilled( false );
// Set up the dialog where we do the actual editing
popup = new PopupDialog();
}
@Override
public Object getCellEditorValue()
{
return currentText;
}
@Override
public Component getTableCellEditorComponent( JTable table, Object value, boolean isSelected, int row, int column )
{
SwingUtilities.invokeLater( new Runnable()
{
@Override
public void run()
{
System.out.println( "run" );
popup.setText( currentText );
Point p = editorComponent1.getLocationOnScreen();
popup.setLocation( p.x, p.y + editorComponent1.getSize().height );
popup.setVisible( true );
fireEditingStopped();
}
} );
currentText = value.toString();
editorComponent1.setText( currentText );
return editorComponent1;
}
/*
* Simple dialog containing the actual editing component
*/
class PopupDialog extends JDialog implements ActionListener
{
private JTextArea textArea;
public PopupDialog()
{
super( (Frame) null, "Change Description", true );
textArea = new JTextArea( 5, 20 );
textArea.setLineWrap( true );
textArea.setWrapStyleWord( true );
KeyStroke keyStroke = KeyStroke.getKeyStroke( "ENTER" );
textArea.getInputMap().put( keyStroke, "none" );
JScrollPane scrollPane = new JScrollPane( textArea );
getContentPane().add( scrollPane );
JButton cancel = new JButton( "Cancel" );
cancel.addActionListener( this );
JButton ok = new JButton( "Ok" );
ok.setPreferredSize( cancel.getPreferredSize() );
ok.addActionListener( this );
JPanel buttons = new JPanel();
buttons.add( ok );
buttons.add( cancel );
getContentPane().add( buttons, BorderLayout.SOUTH );
pack();
getRootPane().setDefaultButton( ok );
}
public void setText( String text )
{
textArea.setText( text );
}
/*
* Save the changed text before hiding the popup
*/
@Override
public void actionPerformed( ActionEvent e )
{
if ( "Ok".equals( e.getActionCommand() ) )
{
currentText = textArea.getText();
}
textArea.requestFocusInWindow();
setVisible( false );
}
}
public static void main( String[] args )
{
String[] columnNames = { "Item", "Description" };
Object[][] data =
{ { "Item 1", "Description of Item 1" }, { "Item 2", "Description of Item 2" }, { "Item 3", "Description of Item 3" } };
JTable table = new JTable( data, columnNames );
table.getColumnModel().getColumn( 1 ).setPreferredWidth( 300 );
table.setPreferredScrollableViewportSize( table.getPreferredSize() );
JScrollPane scrollPane = new JScrollPane( table );
// Use the popup editor on the second column
TablePopupEditor popupEditor = new TablePopupEditor();
table.getColumnModel().getColumn( 1 ).setCellEditor( popupEditor );
JFrame frame = new JFrame( "Popup Editor Test" );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.getContentPane().add( scrollPane );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
}
有可靠的方法来捕获第一个字符吗?
最佳答案
我什至不知道如何将字符附加到文本区域。我尝试调用编辑器大约 200 次,但它只出现一次。所以显然存在一些时间问题。像这样的随机问题通常是代码未在 EDT 上执行的标志。
无论如何,我想出了一个解决方法:
public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected, int row, int column)
{
AWTEvent event = EventQueue.getCurrentEvent();
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
String append = "";
if (event.getID() == KeyEvent.KEY_PRESSED)
{
KeyEvent ke = (KeyEvent)event;
String keyText = ke.getKeyText(ke.getKeyCode());
if (keyText.length() == 1)
append += ke.getKeyChar();
}
popup.setText(currentText + append);
//popup.setLocationRelativeTo( editorComponent );
Point p = editorComponent.getLocationOnScreen();
popup.setLocation(p.x, p.y + editorComponent.getSize().height);
popup.show();
fireEditingStopped();
}
});
currentText = value.toString();
editorComponent.setText( currentText );
return editorComponent;
}
上面的代码保存用于调用编辑器的事件。因此,当显示弹出窗口时,它可以检查按键事件并获取按下的字符。
关于java - JTextArea-Dialog 作为 JTable-CellEditor 错过了第一个键入的字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50256757/