I think you're going to have to listen for the insert key event and simulate "overtype." When you detect the insert key, set a flag. When someone types into your field with the insert flag on, grab the contents of the field, stuff it into a StringBuffer, replace the overtyped character with the typed character and do a setText().
Pretty torturous. If there's an easier way, I'd love to hear it.
Here is a class that allows you to toggle between insert/overtype mode in a JTextArea by extending JTextArea:
http://www.discoverteenergy.com/files/OvertypeTextArea.java
JTextField, JEditorPane, JTextPane could be extended in the same way to provide insert/overtype functionality.
Does anybody know of a way you can provide this functionality for all the JTextComponent classes without extending each class individually?
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.event.*;
import javax.swing.plaf.*;
public class OvertypeTextArea extends JTextArea
{
private static Toolkit toolkit = Toolkit.getDefaultToolkit();
private static boolean isInsertMode;
private Caret defaultCaret;
private Caret overtypeCaret;
public OvertypeTextArea(int row, int column)
{
super(row, column);
setCaretColor( Color.red );
defaultCaret = getCaret();
overtypeCaret = new OvertypeCaret();
overtypeCaret.setBlinkRate( defaultCaret.getBlinkRate() );
setInsertMode( false );
}
/*
*Return the insert/overtype mode
*/
public boolean isInsertMode()
{
return isInsertMode;
}
/*
*Set the caret to use depending on insert/overtype mode
*/
public void setInsertMode(boolean isInsertMode)
{
this.isInsertMode = isInsertMode;
int pos = getCaretPosition();
if (isInsertMode())
{
setCaret( defaultCaret );
}
else
{
setCaret( overtypeCaret );
}
setCaretPosition( pos );
}
/*
* Override method from JComponent
*/
public void replaceSelection(String text)
{
// Implement overtype mode by selecting the character at the current
// caret position
if ( ! isInsertMode() )
{
int pos = getCaretPosition();
if (getSelectedText() == null
&& pos < getDocument().getLength())
{
moveCaretPosition( pos + 1);
}
}
super.replaceSelection(text);
}
/*
* Override method from JComponent
*/
protected void processKeyEvent(KeyEvent e)
{
super.processKeyEvent(e);
// Handle release of Insert key to toggle insert/overtype mode
if (e.getID() == KeyEvent.KEY_RELEASED
&& e.getKeyCode() == KeyEvent.VK_INSERT)
{
setInsertMode( ! isInsertMode() );
}
}
/*
* Paint a horizontal line the width of a column and 1 pixel high
*/
class OvertypeCaret extends DefaultCaret
{
/*
* The overtype caret will simply be a horizontal line one pixel high
* (once we determine where to paint it)
*/
public void paint(Graphics g)
{
if (isVisible())
{
try
{
JTextComponent component = getComponent();
TextUI mapper = component.getUI();
Rectangle r = mapper.modelToView(component, getDot());
g.setColor(component.getCaretColor());
int width = g.getFontMetrics().charWidth( 'w' );
int y = r.y + r.height - 2;
g.drawLine(r.x, y, r.x + width - 1, y);
}
catch (BadLocationException e) {}
}
}
/*
* Damage must be overridden whenever the paint method is overridden
* (The damaged area is the area the caret is painted in. We must
* consider the area for the default caret and this caret)
*/
protected synchronized void damage(Rectangle r)
{
if (r != null)
{
JTextComponent component = getComponent();
x = r.x;
y = r.y;
width = component.getFontMetrics( component.getFont() ).charWidth( 'w' );
height = r.height;
repaint();
}
}
}
public static void main(String[] args)
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
OvertypeTextArea textArea= new OvertypeTextArea(5,20);
textArea.setFont( new Font("monospaced", Font.PLAIN, 12) );
textArea.setText("abcdefg");
frame.getContentPane().add( textArea );
frame.pack();
frame.setVisible(true);
}
}