使用StyledDocument制作单词编辑器会遇到一些麻烦

时间:2019-05-03 00:21:35

标签: java swing jtextpane styleddocument

大家好,这是我的第一个挥杆程序,所以我还有很多东西要学习。我正在制作一个基本的单词编辑器,但使文本加粗时遇到了一些问题。我希望能够用光标在编辑器中突出显示某些内容,当突出显示完成后,突出显示的内容将变为粗体。或者,如果双击一个单词,该单词将变为粗体。我能够成功实现我刚刚解释的内容,但是我有一个撤消按钮。当我单击“撤消”时,它将使编辑器中的所有内容变为粗体。我总结了单词编辑器的许多功能,以使代码简短。您也应该能够复制并粘贴到编辑器中,以查看确切的操作(如果需要)。

import javax.swing.*;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.Style; 
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.StyledDocument;
import java.io.*;
import java.util.Stack;
import java.awt.event.*;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;

public class WordEditor extends JFrame implements KeyListener, ActionListener, Runnable {

private JFrame frame;
private StyledDocument styledDocument;
private JTextPane textPane;
protected static StyleContext editStyles = new StyleContext();

public WordEditor() throws BadLocationException {
      this.styledDocument = new DefaultStyledDocument();
      this.styledDocument.insertString(0, "", null);
      addStylesToDocument(styledDocument);
}

public static void main(String args[]) throws IOException, BadLocationException {
     SwingUtilities.invokeLater(new WordEditor());
}

 @Override
    public void run() {
        JFrame frame = new JFrame("JTextPane Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationByPlatform(true);

        textPane = new JTextPane(styledDocument);
        //textPane.setFont(new Font("Times New Roman", Font.ITALIC, 13));
        textPane.addCaretListener(new SelectedText());
        textPane.setPreferredSize(new Dimension(500, 500));
        //textPane.setBackground(Color.LIGHT_GRAY);
        textPane.addKeyListener(this);
        JScrollPane scrollPane = new JScrollPane(textPane, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
        JMenuBar menuBar = new JMenuBar();


        JMenu doStuffMenu = new JMenu("Actions");
        JMenuItem undoItem = new JMenuItem("Undo");
        JMenuItem redoItem = new JMenuItem("Redo");

        undoItem.addActionListener(this);
        redoItem.addActionListener(this);


        doStuffMenu.add(undoItem);
        doStuffMenu.add(redoItem);
        menuBar.add(doStuffMenu);
        frame.setJMenuBar(menuBar); 
        frame.add(scrollPane);
        frame.pack();
        frame.setVisible(true);
    }

private void addStylesToDocument(StyledDocument styledDocument) {
    Style def = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);
    Style s = styledDocument.addStyle("bold", def);
    StyleConstants.setBold(s, true);
}

int point; // saves the last location of caret for undo/redo
private class SelectedText implements CaretListener {
     public void caretUpdate(CaretEvent event) {
            point = event.getDot();
            int dot = event.getDot();
            int mark = event.getMark();
            System.out.println("dot: " + dot);
            System.out.println("mark: " + mark);
            if (dot != mark) {
                if (dot < mark) {
                    int temp = dot;
                    dot = mark;
                    mark = temp;
                }
                System.out.println("MAKING BOLD!"); // does not print when undo is pressed
                boldSelectedText(mark, dot);
            } else {  // if it doesn't bold make it times new Roman... doesnt work.
                textPane.setFont(new Font("Times New Roman", Font.PLAIN, 13));  
            }
     }
}

private void boldSelectedText(int mark, int dot) {
    try {
        int length = dot - mark;
        String s = styledDocument.getText(mark, length);
        styledDocument.remove(mark, length);
        styledDocument.insertString(mark, s, styledDocument.getStyle("bold"));
    } catch (BadLocationException e) {
        e.printStackTrace();
    }
}


public void keyPressed(KeyEvent e) {
}

public void keyReleased(KeyEvent e) {
}

Stack<String> listUndo = new Stack<String>();
Stack<String> listRedo = new Stack<String>();
char redoEndHold = ' ';
int numKeysTyped = 0;
String text = "";
public void keyTyped(KeyEvent e) {  
    text = textPane.getText();
    redoEndHold = e.getKeyChar();
    listUndo.push(text);
    numKeysTyped++;
}


int undoCounter = 0;
int redoPopManager = 0;
boolean redoPushManager = false;
boolean undoHasBeenPressed = false;
public void undo() {
    if (listUndo.size() > 0) {
        if (undoCounter < 10) {
            String hold = listUndo.pop();
            if (undoCounter == 0) {
                System.out.println("pushing extra character");
                if(point - 1 == text.length()) {
                    if (redoPushManager == false) {
                        listRedo.push(hold + redoEndHold);
                    } else {
                        listRedo.push(hold);
                    }
                } else {
                    String part1 = text.substring(0, point - 1);
                    String part2 = text.substring(point - 1); 
                    listRedo.push(part1 + redoEndHold + part2);
                }
            }
            listRedo.push(hold);
            undoCounter++;
            textPane.setText(hold);
            undoHasBeenPressed = true;
        } else {
            JOptionPane.showMessageDialog(frame, "ERROR: max undo length of 10 reached");
        }
    } else {
        JOptionPane.showMessageDialog(frame, "ERROR: Undo List is empty");
    }
}

public void redo() {
    if (listRedo.size() > 0) {
        if (undoCounter >= 0) {
            String hold = listRedo.pop();
            if (redoPopManager == 0) {
                hold = listRedo.pop();
                System.out.println("worked");
            }
            textPane.setText(hold);
            redoPopManager++;
            undoCounter--;
            if (undoCounter == 0) {
                JOptionPane.showMessageDialog(frame, "just letting you know No more undos to redo! hit enter to continue");
                redoPopManager = 0;
                redoPushManager = true;
            }
        } else {
            JOptionPane.showMessageDialog(frame, "ERROR: No more undos to redo!");
        }
    } else {
        JOptionPane.showMessageDialog(frame, "ERROR: Redo list is empty!");
    }
}

public void actionPerformed(ActionEvent e) {
    String action = e.getActionCommand();
    System.out.println(e.getActionCommand());
    if (action.equals("Undo")) {
        undo();
    } else if (action.equals("Redo")) {
        redo();
    }
}
}

我希望撤消按钮仅撤消最近键入的字符。它可以做到,但是如果我将单个字符设为粗体,它也会使所有内容变为粗体。我的预期结果是例如输入“ hello”。我突出显示了el和o,所以它变粗了。我单击撤消,它摆脱了加粗的o。现在剩下的是h不粗体,e粗体,l粗体,l不粗体。请让我知道我是否需要更具体地询问我的问题。

0 个答案:

没有答案