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