java - 按 Ctrl+A 正在更改 JTextPane 中的字体

标签 java swing jtextpane

我正在使用 Java Swing 和 JTextPane 组件创建一个简单的文本编辑器。我添加了将文本设置为粗体、斜体、下划线的代码,并且还添加了获取 JComboBox 中的系统字体的代码,以便我可以更改 JTextPane 内容的字体。并且如果内容有多种字体样式,则会根据光标位置显示对应的字体名称。

我有一个问题:如果内容有多种字体样式,按 Ctrl+A 会选择所有内容,并且会将整个内容字体更改为相同字体(即第一行的字体样式) 。在按 Ctrl+A 之前:

Before pressing Ctrl+A

按Ctrl+A后,第一行的字体样式-Calibri字体将应用到所有三行,如下图:

enter image description here

这是最简单的代码

import java.awt.BorderLayout;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.SwingUtilities;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledEditorKit;
import javax.swing.text.rtf.RTFEditorKit;

public class Editor2 {
    private JTextPane editor;
    private DefaultStyledDocument doc;
    private DefaultComboBoxModel<String> fontFamilyComboBoxModel;
    private JComboBox<String> fontSizeComboBox;
    private JComboBox<String> fontFamilyComboBox;
    private AttributeSet attrs;
    private String fontFamilyStr;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new Editor2().createAndShowGUI();
            }
        });
    }

    private void createAndShowGUI() {
        editor = new JTextPane();
        editor.setMargin(new Insets(5, 5, 5, 5));
        RTFEditorKit rtf = new RTFEditorKit();
        editor.setEditorKit(rtf);
        editor.addCaretListener(new MyCaretListener());
        JScrollPane editorScrollPane = new JScrollPane(editor);
        doc = new DefaultStyledDocument();
        initDocAttrs();
        editor.setDocument(doc);
        final String[] fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
        fontFamilyComboBoxModel = new DefaultComboBoxModel<>(fonts);
        fontFamilyComboBox = new JComboBox<String>(fontFamilyComboBoxModel);
        fontFamilyComboBox.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                String name = (String) fontFamilyComboBox.getSelectedItem();
                new StyledEditorKit.FontFamilyAction("font-family-" + name, name).actionPerformed(ae);
                editor.requestFocus();
            }
        });

        final String[] fontSizes = { "Font Size", "10", "11", "12", "14", "16", "18", "20", "24", "28", "30", "34",
                "40", "50" };
        fontSizeComboBox = new JComboBox<String>(fontSizes);
        fontSizeComboBox.setEditable(false);

        JFrame frame = new JFrame("Text Editor");
        frame.add(fontFamilyComboBox, BorderLayout.SOUTH);
        frame.add(fontSizeComboBox, BorderLayout.NORTH);
        frame.add(editorScrollPane, BorderLayout.CENTER);
        frame.add(editorScrollPane);
        frame.setSize(800, 400);
        frame.setLocation(300, 150);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        editor.requestFocusInWindow();
    }

    private void initDocAttrs() {
        Style style = doc.addStyle("my_doc_style", null);
        StyleConstants.setFontSize(style, 12);
        StyleConstants.setFontFamily(style, "Arial");
        doc.setParagraphAttributes(5, doc.getLength(), style, true);
    }

    private class MyCaretListener implements CaretListener {
        @Override
        public void caretUpdate(CaretEvent e) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    attrs = ((StyledEditorKit) editor.getEditorKit()).getInputAttributes();
                    System.out.println(attrs);
                    fontFamilyStr = (String) attrs.getAttribute(StyleConstants.FontFamily);
                    System.out.println("Font: " + fontFamilyStr);
                    fontFamilyComboBox.setSelectedItem(fontFamilyStr);
                }
            });
            System.out.println("---");
        }
    }
}

为什么按Ctrl+A会改变所有字体样式?谁能帮我解决这个问题吗?

最佳答案

fontFamilyComboBox.setSelectedItem(fontFamilyStr);

在您的 CaretListener 中,您正在更改所选项目,这会导致调用组合框的 ActionListener,从而导致您更改所选文本的字体.

一种解决方案是在更改所选项目之前从组合框中删除 ActionListner:

comboBox.removeActionListener(...);
comboBox.setSelectedItem(fontFamilyStr);
comboBox.addActionListener(..)

关于java - 按 Ctrl+A 正在更改 JTextPane 中的字体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53219470/

相关文章:

java - 如何使用 for 循环在 if 条件为 true 时始终将字符串更改为另一个字符串并更改为数组中的另一个

java - Maven 模块看不到可靠的子模块

java - map View 的 AlertDialog.Builder 的默认上下文?

java - 如何制作 JScrollPane/JTextPane "Intelligent"

java - Swing 工作线程 : Inner class vs passing parameter

JavaScript 变量名正则表达式

java - addMouseListener 不适用于标签

java - UIManager 字符串

java - 如何比较 java swing 按钮图标以检查相等性?

java - Jtextpane 复制彩色文本并粘贴