How to override DefaultCaret # setBlinkRate ()

  • I have a problem with Caret, Caret does not blink without focusGained (see code in Swing Action) until the 2nd. JTextField and back to 1st. JTextField

  • how to change DefaultCaret # setBlinkRate () correctly

  • (without overriding Caret), the default is Caret at the end of the document and flashes 1. focusGained


  • tested on win7_32b, Java7.011 / 025 / Java6

  • tested with several standard L & Fs, custom, each of which caused the same problem

  • see in more detail my answer to the question How to save selected text in JTextField when focus is lost? and possible workaround by @kleopatra


my sscce

import java.awt.*; import java.awt.event.ActionEvent; import javax.swing.*; import javax.swing.text.DefaultCaret; import javax.swing.text.DefaultHighlighter; import javax.swing.text.Highlighter; public class TestTextComponents { private static final long serialVersionUID = 1L; private Timer timer; private JTextField jTextField0 = new JTextField(); private JTextField jTextField1 = new JTextField(); private JTextField jTextField2 = new JTextField(); private JFrame frame = new JFrame("Default Caret"); private JPanel panel = new JPanel(); public TestTextComponents() { jTextField0.setText("jTextField0"); jTextField1.setText("jTextField1"); jTextField2.setText("jTextField2"); jTextField1.setCaret(new HighlightCaret()); jTextField2.setCaret(new HighlightCaret()); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); panel.add(new JLabel("Please skip between text fields and watch persistent selection: ")); panel.add(jTextField0); panel.add(jTextField1); panel.add(jTextField2); frame.add(panel); frame.setTitle("Text component persistent selection"); frame.pack(); frame.setVisible(true); /*timer = new javax.swing.Timer(250, updateCol()); timer.setRepeats(false); timer.start();*/ } private Action updateCol() { return new AbstractAction("Hello World") { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent e) { jTextField2.grabFocus(); jTextField2.requestFocusInWindow(); jTextField1.grabFocus(); jTextField1.requestFocusInWindow(); } }; } private class HighlightCaret extends DefaultCaret { private static final long serialVersionUID = 1L; private final Highlighter.HighlightPainter unfocusedPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.RED); private final Highlighter.HighlightPainter focusedPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.ORANGE); private boolean isFocused; @Override protected Highlighter.HighlightPainter getSelectionPainter() { return isFocused ? focusedPainter /*super.getSelectionPainter()*/ : unfocusedPainter; } @Override public void setSelectionVisible(boolean hasFocus) { super.repaint(); super.setBlinkRate(500); if (hasFocus != isFocused) { isFocused = hasFocus; super.setSelectionVisible(false); super.setSelectionVisible(true); } } } public static void main(String args[]) { /*try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) { e.printStackTrace(); } try { for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) { if ("Nimbus".equals(laf.getName())) { UIManager.setLookAndFeel(laf.getClassName()); } } } catch (Exception e) { e.printStackTrace(); }*/ SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new TestTextComponents(); } }); } } 
+3
java swing caret jtextfield
source share
3 answers

The flashing caret is controlled by the setVisible() DefaultCaret method. Selected text is controlled using the setSelectionVisible() method.

focusGained/focusLost DefaultCaret methods to control Caret behavior using these two methods. By default for focusCained, both properties are true. On focusLost, they are set to false. Using your main logic for different markers, 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 boxes, but only the text box with focus will blink.

+2
source share

I have found a solution. Override the focusGained method of your HighlightCaret and set the blink speed there.

  @Override public void focusGained(FocusEvent e) { isFocused = true; super.setBlinkRate(500); super.focusGained(e); } 

This helped me in OS X.

+2
source share

But your previous code works fine if setBlinkRate(500); fits into the constructor of the HighlightCaret class:

 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 this?

+1
source share

All Articles