I have an problem with Caret, Caret didn\'t blink without focusGained(see code in Swing Action) to 2nd. JTextField and back to 1st. JTextField
how
But your previous code works OK if setBlinkRate(500);
is placed in HighlightCaret
class constructor:
class HighlightCaret extends DefaultCaret {
private static final Highlighter.HighlightPainter unfocusedPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.RED);
private static final Highlighter.HighlightPainter focusedPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.YELLOW);
private static final long serialVersionUID = 1L;
private boolean isFocused;
HighlightCaret(){
setBlinkRate(500);//Placed here
}
@Override
protected Highlighter.HighlightPainter getSelectionPainter() {
// setBlinkRate(500); // otherwise is disabled, stopped
return isFocused ? focusedPainter/*super.getSelectionPainter()*/ : unfocusedPainter;
}
@Override
public void setSelectionVisible(boolean hasFocus) {
if (hasFocus != isFocused) {
isFocused = hasFocus;
super.setSelectionVisible(false);
super.setSelectionVisible(true);
}
}
}
Tested in Java7 WinXP. Have you tried it?
The blinking caret is controlled by the setVisible()
method of the DefaultCaret. The selected text is controlled by the setSelectionVisible()
method.
The focusGained/focusLost
methods of the DefaultCaret to control behaviour of the Caret using these two methods. By default on focusGained both properties are set to true. On focusLost they are set to false. Using your basic logic for different highlighters you can do something like:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
public class SelectionCaret extends DefaultCaret
{
private final Highlighter.HighlightPainter unfocusedPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.RED);
private final Highlighter.HighlightPainter focusedPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.ORANGE);
public SelectionCaret()
{
setBlinkRate( UIManager.getInt("TextField.caretBlinkRate") );
}
@Override
protected Highlighter.HighlightPainter getSelectionPainter()
{
return getComponent().hasFocus() ? focusedPainter : unfocusedPainter;
}
@Override
public void focusGained(FocusEvent e)
{
setSelectionVisible(false);
super.focusGained(e);
}
@Override
public void focusLost(FocusEvent e)
{
super.focusLost(e);
setSelectionVisible(true);
}
private static void createAndShowUI()
{
JTextField textField1 = new JTextField("Text Field1 ");
JTextField textField2 = new JTextField("Text Field2 ");
JTextField textField3 = new JTextField("Non Editable ");
textField3.setEditable(false);
textField1.setCaret(new SelectionCaret());
textField2.setCaret(new SelectionCaret());
textField3.setCaret(new SelectionCaret());
textField1.select(5, 11);
textField2.select(5, 11);
textField3.select(5, 11);
((DefaultCaret)textField1.getCaret()).setSelectionVisible(true);
((DefaultCaret)textField2.getCaret()).setSelectionVisible(true);
((DefaultCaret)textField3.getCaret()).setSelectionVisible(true);
JPanel north = new JPanel();
north.add( new JTextField("Text Field0 ") );
north.add(textField1);
north.add(textField2);
north.add(textField3);
JFrame frame = new JFrame("Selection Caret");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( north );
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
Now any text will be selected in both text fields, but only the text field with focus will blink.
I have found the solution. Override the focusGained
method of your HighlightCaret
and set the blink rate there as well.
@Override
public void focusGained(FocusEvent e)
{
isFocused = true;
super.setBlinkRate(500);
super.focusGained(e);
}
This did the trick for me in OS X.