在setText()之后的JEditorPane焦点问题

时间:2012-02-15 22:44:40

标签: java swing focus jeditorpane

尝试使用Tab键设置焦点在JEditorPane时,我的应用程序出现问题。起初我不明白为什么,但我设法做了一个小的测试用例来证明这个问题。

public class JEditorPaneFocusTest
{
    public static void main(String... args) throws Exception
    {
        JFrame jFrame = new JFrame();
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Container container = jFrame.getContentPane();
        container.setLayout(new BorderLayout());

        container.add(new JTextField(), BorderLayout.NORTH);

        JEditorPane editorPane = new JEditorPane();
        editorPane.setEditorKit(new HTMLEditorKit());
        editorPane.setText("<html><body>Hello World</body></html>");
        container.add(editorPane, BorderLayout.CENTER);

        jFrame.setSize(new Dimension(400, 400));
        jFrame.setVisible(true);
    }
}

(在Windows 7和Mac OS X Lion上测试过。)应用程序将首先关注JTextField。使用tab键不会将焦点设置为JEditorPane。但是如果你评论setText行,它似乎有用......

有什么想法吗?

2 个答案:

答案 0 :(得分:4)

  • 简短回答

通过包装到invokeLater()

来延迟此事件
  • 更长的回答

Focus / Focus Subsystem是异步的,在大多数情况下难以管理/计时此/偶数,为了更好地理解这个问题,您必须阅读链接教程,

关于焦点问题的例子

import java.awt.*;
import java.awt.event.*;
import java.awt.font.TextAttribute;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.util.Map;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.*;

public class TextAttributeSTRIKETHROUGH {

    private JFrame frame = new JFrame();
    private JPanel pnl = new JPanel();
    private JLabel focusLabel = new JLabel(" focusLost Handle ");
    private JFormattedTextField formTextField;
    private JLabel docLabel = new JLabel(" document Handle ");
    private JFormattedTextField formTextField1;
    private NumberFormat formTextFieldFormat;
    private double amount = 10000.00;
    private Map attributes;

    @SuppressWarnings("unchecked")
    public TextAttributeSTRIKETHROUGH() {
        formTextFieldFormat = NumberFormat.getNumberInstance();
        formTextFieldFormat.setMinimumFractionDigits(2);
        formTextFieldFormat.setMaximumFractionDigits(2);
        formTextFieldFormat.setRoundingMode(RoundingMode.HALF_UP);

        focusLabel.setFont(new Font("Serif", Font.BOLD, 14));
        focusLabel.setForeground(Color.blue);
        focusLabel.setPreferredSize(new Dimension(120, 27));
        formTextField = new JFormattedTextField(formTextFieldFormat);
        formTextField.setValue(amount);
        formTextField.setFont(new Font("Serif", Font.BOLD, 22));
        formTextField.setForeground(Color.black);
        formTextField.setBackground(Color.yellow);
        formTextField.setPreferredSize(new Dimension(120, 27));
        formTextField.setHorizontalAlignment(SwingConstants.RIGHT);
        formTextField.addFocusListener(new FocusListener() {

            @Override
            public void focusGained(FocusEvent e) {
                formTextField.requestFocus();
                formTextField.setText(formTextField.getText());
                formTextField.selectAll();
            }

            public void focusLost(FocusEvent e) {
                //Runnable doRun = new Runnable() {

                //@Override
                //public void run() {
                double t1a1 = (((Number) formTextField.getValue()).doubleValue());
                if (t1a1 < 1000) {
                    formTextField.setValue(amount);
                }
                //}
                // };
                //SwingUtilities.invokeLater(doRun);
            }
        });

        docLabel.setFont(new Font("Serif", Font.BOLD, 14));
        docLabel.setForeground(Color.blue);
        docLabel.setPreferredSize(new Dimension(120, 27));

        formTextField1 = new JFormattedTextField(formTextFieldFormat);
        formTextField1.setValue(amount);
        formTextField1.setFont(new Font("Serif", Font.BOLD, 22));
        formTextField1.setForeground(Color.black);
        formTextField1.setBackground(Color.yellow);
        formTextField1.setPreferredSize(new Dimension(120, 27));
        formTextField1.setHorizontalAlignment(SwingConstants.RIGHT);
        formTextField1.addFocusListener(new FocusListener() {

            @Override
            public void focusGained(FocusEvent e) {
                formTextField1.requestFocus();
                formTextField1.setText(formTextField1.getText());
                formTextField1.selectAll();
            }

            @Override
            public void focusLost(FocusEvent e) {
            }
        });
        formTextField1.getDocument().addDocumentListener(docListener);

        attributes = (new Font("Serif", Font.BOLD, 24)).getAttributes();
        attributes.put(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON);

        pnl = new JPanel();
        pnl.setBorder(new EmptyBorder(2, 2, 2, 2));
        pnl.setLayout(new GridLayout(2, 2));
        pnl.add(focusLabel);
        pnl.add(formTextField);
        pnl.add(docLabel);
        pnl.add(formTextField1);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(pnl, BorderLayout.CENTER);
        frame.setLocation(200, 200);
        frame.pack();
        frame.setVisible(true);
        formTextFieldFocus1();
    }
    //
    private DocumentListener docListener = new DocumentListener() {

        @Override
        public void changedUpdate(DocumentEvent documentEvent) {
            printIt(documentEvent);
        }

        @Override
        public void insertUpdate(DocumentEvent documentEvent) {
            printIt(documentEvent);
        }

        @Override
        public void removeUpdate(DocumentEvent documentEvent) {
            printIt(documentEvent);
        }

        private void printIt(DocumentEvent documentEvent) {
            DocumentEvent.EventType type = documentEvent.getType();
            double t1a1 = (((Number) formTextField1.getValue()).doubleValue());
            if (t1a1 < 1000) {
                Runnable doRun = new Runnable() {

                    @Override
                    public void run() {
                        formTextField1.setFont(new Font(attributes));
                    }
                };
                SwingUtilities.invokeLater(doRun);
            } else {
                Runnable doRun = new Runnable() {

                    @Override
                    public void run() {
                        formTextField1.setFont(new Font("Serif", Font.BOLD, 22));
                    }
                };
                SwingUtilities.invokeLater(doRun);
            }
        }
    };

    private void formTextFieldFocus1() {
        Runnable doRun = new Runnable() {

            @Override
            public void run() {
                formTextField1.grabFocus();
                formTextField1.requestFocus();
                formTextField1.setText(formTextField1.getText());
                formTextField1.selectAll();
            }
        };
        SwingUtilities.invokeLater(doRun);
    }

    private void formTextFieldFocus() {
        Runnable doRun = new Runnable() {

            @Override
            public void run() {
                formTextField.grabFocus();
                formTextField.requestFocus();
                formTextField.setText(formTextField.getText());
                formTextField.selectAll();
                formTextFieldFocus1();
            }
        };
        SwingUtilities.invokeLater(doRun);
    }

    public static void main(String args[]) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                TextAttributeSTRIKETHROUGH fl = new TextAttributeSTRIKETHROUGH();
            }
        });
    }
}

答案 1 :(得分:3)

所有与GUI相关的代码都应该在EDT上执行。有关详细信息,请参阅Concurrency in Swing

import java.awt.*;
import javax.swing.*;
import javax.swing.text.html.*;

public class JEditorPaneFocusTest
{
    public static void main(String... args) throws Exception
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                JFrame jFrame = new JFrame();
                jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                Container container = jFrame.getContentPane();
                container.setLayout(new BorderLayout());

                container.add(new JTextField(), BorderLayout.NORTH);

                JEditorPane editorPane = new JEditorPane();
                editorPane.setEditorKit(new HTMLEditorKit());
                editorPane.setText("<html><body>Hello World</body></html>");
                container.add(editorPane, BorderLayout.CENTER);

                jFrame.setSize(new Dimension(400, 400));
                jFrame.setVisible(true);
            }
        });

    }
}