制作 Java WYSIWYG 编辑器 - 通过按钮样式显示样式不起作用?

问题描述 投票:0回答:1

出于学习目的,我正在用 Java 从头开始制作一个所见即所得编辑器。现在我想让用户可以知道什么样式将应用于下一个键入的字符,通过按下/样式化按钮来指示它们存在,但它现在不起作用。

我当前的 JToolBar 代码 -

public class ToolBar extends JToolBar {
    private final JTextPane textPane;
    private final StyledEditorKit.BoldAction boldAction = new StyledEditorKit.BoldAction();
    private final StyledEditorKit.UnderlineAction underlineAction = new StyledEditorKit.UnderlineAction();
    private final StyledEditorKit.ItalicAction italicAction = new StyledEditorKit.ItalicAction();
    private JButton boldBtn;
    private JButton italicsBtn;
    private JButton  underlineBtn;
    private final Color defaultColor = new Color(238,238,238);
    private final Color selectedColor = new Color(100,100,100);
    public ToolBar(JTextPane textPane) {
        super("WYSIWYG Tools");
        this.textPane = textPane;
        setFloatable(false);
        setupButtons();
        updateButtonStates();
        textPane.addCaretListener(e -> updateButtonStates());
    }
    private void setupButtons() {
        boldBtn = createImageButton("src/resources/images/bold.png");
        boldBtn.addActionListener(this::boldStylize);
        italicsBtn = createImageButton("src/resources/images/italics.png");
        italicsBtn.addActionListener(this::italicStylize);
        underlineBtn = createImageButton("src/resources/images/underline.png");
        underlineBtn.addActionListener(this::underlineStylize);
        JButton strikeBtn = createImageButton("src/resources/images/strike.png");
        add(boldBtn);
        add(italicsBtn);
        add(underlineBtn);
        add(strikeBtn);
    }
    private static JButton createImageButton(String imagePath) {
        JButton button = new JButton();
        try {
            BufferedImage image = ImageIO.read(new File(imagePath));
            button.setIcon(new ImageIcon(image));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return button;
    }
    private void boldStylize(ActionEvent e) {
        textPane.requestFocusInWindow();
        boldAction.actionPerformed(new ActionEvent(textPane, ActionEvent.ACTION_PERFORMED, null));
        updateButtonStates();
    }
    private void underlineStylize(ActionEvent e) {
        textPane.requestFocusInWindow();
        underlineAction.actionPerformed(new ActionEvent(textPane, ActionEvent.ACTION_PERFORMED, null));
        updateButtonStates();
    }
    private void italicStylize(ActionEvent e) {
        textPane.requestFocusInWindow();
        italicAction.actionPerformed(new ActionEvent(textPane, ActionEvent.ACTION_PERFORMED, null));
        updateButtonStates();
    }
    private void updateButtonStates() {
        System.out.println("updating button states");
        StyledDocument doc = textPane.getStyledDocument();
        int caretPosition = textPane.getCaretPosition();
        System.out.println("Caret positions " + caretPosition);
        Element paragraphElement = doc.getParagraphElement(caretPosition);
        AttributeSet attrs = paragraphElement.getAttributes();
        //The above will tell us the current style of things
        boolean isBold = StyleConstants.isBold(attrs);
        boolean isItalics = StyleConstants.isItalic(attrs);
        boolean isUnderline = StyleConstants.isUnderline(attrs);
        System.out.println(String.format("bold %b italics %b underline %b", isBold, isItalics, isUnderline));
        if (isBold) {
            boldBtn.setBackground(selectedColor);
        } else {
            boldBtn.setBackground(defaultColor);
        }
        if (isItalics) {
            italicsBtn.setBackground(selectedColor);
        } else {
            italicsBtn.setBackground(defaultColor);
        }
        if (isUnderline) {
            underlineBtn.setBackground(selectedColor);
        } else {
            underlineBtn.setBackground(defaultColor);
        }
    }
}

我相信问题是我的

updateStateButtons
函数的前几行,
attrs
总是将我的所有样式返回为 false,尽管在我的 TextPane 中输入时我看到了样式。

我之前尝试过


        StyledDocument doc = textPane.getStyledDocument();
        AttributeSet attrs = doc.getCharacterElement(textPane.getSelectionStart()).getAttributes();

这种方法有效 - 如果我突出显示一个选择并应用粗体,则粗体按钮将突出显示。然后,如果我继续打字,它就会保持突出显示状态。但如果我转到文本末尾,它会取消突出显示,但我要输入的下一个字符仍然是粗体。

我考虑过手动切换,但我认为可能会不同步,最好从文档中读取样式,但我显然没有完全正确地做到这一点。有谁知道我如何修改它,以便我可以向用户展示下一个字符的样式?

java swing
1个回答
0
投票

您想使用

CaretListener
检查属性的当前状态。

JTextPane
确实有一个
getInputAttributes()
方法,对我来说应该是使用的方法。但是,它对我不起作用。当插入符号位于第一个风格化字符之前时,这意味着要键入的下一个字符应该风格化,但事实并非如此。

因此,以下代码将插入符号位置调整 1,这似乎给出了正确的结果:

import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;

public class TextPaneCaret
{
    private static void createAndShowGUI()
    {
        JButton bold = new JButton( new StyledEditorKit.BoldAction() );

        JTextPane textPane = new JTextPane();
        textPane.setText("Now is the time for...");
        JScrollPane scrollPane = new JScrollPane( textPane );
        scrollPane.setPreferredSize( new Dimension( 200, 200 ) );

        textPane.addCaretListener((e) ->
        {
            StyledDocument doc = textPane.getStyledDocument();
            int offset = textPane.getCaretPosition();

            if (offset > 0)
                offset--;

            Element characterElement = doc.getCharacterElement(offset);
            AttributeSet attributes = characterElement.getAttributes();

            System.out.println( attributes.containsAttribute(StyleConstants.Bold, Boolean.TRUE) );
        });

        JFrame frame = new JFrame("SSCCE");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(bold, BorderLayout.PAGE_START);
        frame.add(scrollPane, BorderLayout.CENTER);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationByPlatform( true );
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        java.awt.EventQueue.invokeLater( () -> createAndShowGUI() );
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.