我们需要CellEditor
JTable
来编辑大型多行文字。
我们尝试使用一个可视化扩展TableCell
的弹出框,它将细胞重叠到右边和底部。如果单元格位于右下角,靠近屏幕边界等,则会导致各种问题。
然后我们决定使用模式 JDialog
来编辑单元格值。因此用户可以移动对话框,我们可以坚持其大小和位置。
现在问题开始了;-)
我们无法将第一个键入的字符“转发”到对话框。
堆栈溢出有很多例子,这个问题在自定义CellEditor
中得到解决,自定义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 );
}
}
直接显示在表(单元格)中,例如:Losing first character in JTable panel based cell editor
以下SSCCE(来自camickrs回答:https://stackoverflow.com/a/3591230/361227)显示第二个TableColumn中的第一次击键大部分时间都会丢失。
$index = array_search(count_chars($content), array_map('count_chars', $fruits));
有没有可靠的方法来捕捉第一个角色?
答案 0 :(得分:1)
我甚至无法弄清楚角色是如何附加到文本区域的。我尝试了大约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;
}
上面的代码保存了用于调用编辑器的事件。因此,当弹出窗口显示时,它可以检查键事件并获取按下的字符。