создание текстового редактора с использованием StyledDocument с некоторыми проблемами - PullRequest
0 голосов
/ 03 мая 2019

Привет, ребята, это моя первая свинговая программа, так что мне еще есть чему поучиться.Я делаю простой редактор слов, и у меня есть несколько проблем с выделением текста жирным шрифтом.Я хочу иметь возможность выделить что-то в редакторе с помощью курсора, и когда я закончу выделение, все, что было выделено, станет жирным.Или, если дважды щелкнуть слово, слово станет жирным.Мне удалось успешно реализовать то, что я только что объяснил, однако, у меня есть кнопка отмены.Когда я нажимаю «Отменить», в редакторе все будет выделено жирным шрифтом.Я использовал много возможностей редактора слов, чтобы код был коротким.Вы должны быть в состоянии скопировать и вставить в редактор, чтобы точно увидеть, что происходит, если вы тоже хотите.

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

Я хочу, чтобы кнопка отмены просто отменяла самый последний набранный символ.Что и происходит, но все становится жирным, если я выделю один символ жирным шрифтом.Мой ожидаемый результат - например, я набираю «привет».Я выделяю el и o, чтобы он получился жирным.Я нажимаю «Отменить», и он избавляется от жирного шрифта.То, что у меня осталось, теперь не жирный, жирный, жирный, не жирный.Пожалуйста, дайте мне знать, если мне нужно быть более точным в том, что я спрашиваю.

...