• 我对插入符号有问题,如果没有focusGained(请参见Swing Action中的代码)排到第二位,插入符号不会闪烁。 JTextField并回到1st。 JTextField
  • 如何正确覆盖DefaultCaret#setBlinkRate()
  • (无替代插入符号)默认为文档末尾的插入符号,并在1日闪烁。 focus获得


  • 已在win7_32b,Java7.011 / 025 / Java6
  • 上进行了测试
  • 也使用一些标准L&F(自定义)进行了测试,每一个都引起了相同的问题
  • 请查看更多详细信息,我对问题How to retain selected text in JTextField when focus lost?possible workaround by @kleopatra的回答


  • 我的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();
                }
            });
        }
    }
    

    最佳答案

    闪烁的插入符号由DefaultCaret的setVisible()方法控制。所选文本由setSelectionVisible()方法控制。

    DefaultCaret的focusGained/focusLost方法可使用这两种方法控制插入符的行为。默认情况下,focusGained上的两个属性均设置为true。在focusLost上,它们设置为false。将基本逻辑用于不同的荧光笔,您可以执行以下操作:

    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();
                }
            });
        }
    }
    

    现在,将在两个文本字段中都选择任何文本,但是只有具有焦点的文本字段才会闪烁。

    08-04 12:36