java - 如何使用 Swing 实现撤消和重做操作

标签 java swing undo-redo

我编写了撤消和重做操作的逻辑。但是,它无法正常工作。当我打开文件然后单击“回滚”时,整个文件内容被删除,当我使用替换菜单项替换任何Word时,然后我点击回滚 替换文本不回滚,整个文本被删除。请帮助我。谢谢。

我的代码:

public class UndoAndRedoAction extends javax.swing.JFrame {
JTextArea text;
int i=0;
UndoManager undoManager = new UndoManager();
public UndoAndRedoAction() {
    initComponents();
    text = new JTextArea();
    rollback.setEnabled(false);
    redo.setEnabled(false);
}
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">                          
private void initComponents() {

    tp = new javax.swing.JTabbedPane();
    jMenuBar1 = new javax.swing.JMenuBar();
    fileMenu = new javax.swing.JMenu();
    open = new javax.swing.JMenuItem();
    rollback = new javax.swing.JMenuItem();
    redo = new javax.swing.JMenuItem();
    replace = new javax.swing.JMenuItem();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

    fileMenu.setText("File");

    open.setText("Open");
    open.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            openActionPerformed(evt);
        }
    });
    fileMenu.add(open);

    rollback.setText("Rollback");
    rollback.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            rollbackActionPerformed(evt);
        }
    });
    fileMenu.add(rollback);

    redo.setText("Redo");
    redo.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            redoActionPerformed(evt);
        }
    });
    fileMenu.add(redo);

    replace.setText("Replace");
    replace.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            replaceActionPerformed(evt);
        }
    });
    fileMenu.add(replace);

    jMenuBar1.add(fileMenu);

    setJMenuBar(jMenuBar1);

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addComponent(tp, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addComponent(tp, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 279, Short.MAX_VALUE)
    );

    pack();
}// </editor-fold>                        

private void openActionPerformed(java.awt.event.ActionEvent evt) {                                     
    final JFileChooser jc = new JFileChooser();
    int returnVal=  jc.showOpenDialog(UndoAndRedoAction.this);
    String title;
    File file=null;
    if(returnVal == JFileChooser.APPROVE_OPTION)
    file = jc.getSelectedFile();
    if (jc.getSelectedFile()!= null) {   
        BufferedReader br = null;
        StringBuffer str = new StringBuffer("");
        try {
            br = new BufferedReader(new FileReader(file));
            String line;
            while ((line = br.readLine()) != null) {
                str.append(line + "\n");
            }
        }
        catch (IOException ex) {
            Logger.getLogger(UndoAndRedoAction.class.getName()).log(Level.SEVERE, null, ex);
        }
        String t = str.toString();
        final JInternalFrame internalFrame = new JInternalFrame("",true,true);
        title=file.getName();
        text.setFont(new java.awt.Font("Miriam Fixed", 0, 13));
        internalFrame.add(text);
        i+=1;
        internalFrame.setName("Doc "+i);
        JScrollPane scrollpane=new JScrollPane(text);
        internalFrame.setTitle(title);
        tp.add(internalFrame);
        internalFrame.add(scrollpane);
        internalFrame.setVisible(true);
        text.setText(t);
        text.setCaretPosition(0);
        text.getDocument().addUndoableEditListener(new UndoableEditListener() {
            @Override
            public void undoableEditHappened(UndoableEditEvent e) {
                undoManager.addEdit(e.getEdit());
                rollback.setEnabled(undoManager.canUndo());
                redo.setEnabled(undoManager.canRedo());
            }
        });


    }
}                                    

private void rollbackActionPerformed(java.awt.event.ActionEvent evt) {                                         
    rollback.setEnabled(undoManager.canUndo());
    if (undoManager.canUndo()) {
        undoManager.undo();
    }
    rollback.setEnabled(undoManager.canUndo());
    redo.setEnabled(undoManager.canRedo());
}                                        

private void redoActionPerformed(java.awt.event.ActionEvent evt) {                                     
    redo.setEnabled(undoManager.canRedo());
    if (undoManager.canRedo()) {
        undoManager.redo();
    }
    rollback.setEnabled(undoManager.canUndo());
    redo.setEnabled(undoManager.canRedo());
}                                    

private void replaceActionPerformed(java.awt.event.ActionEvent evt) {                                        
    JDialog replace_dialog=new JDialog(UndoAndRedoAction.this);
    replace_dialog.setTitle("Replace");
    JLabel find_label=new JLabel("Find what");
    final JTextField find_tf=new JTextField(10);
    JLabel replace_label=new JLabel("Replace With");
    final JTextField replace_tf=new JTextField(10);
    JButton replaceAll=new JButton("Replace All");
    replace_dialog.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.insets = new Insets(5, 5, 5, 5);
    c.gridx = 0;
    c.gridy = 0;
    c.anchor = GridBagConstraints.WEST;
    replace_dialog.add(find_label, c);
    c.gridx++;
    c.fill = GridBagConstraints.HORIZONTAL;
    c.weightx = 1;
    replace_dialog.add(find_tf, c);
    c.gridx = 0;
    c.gridy = 1;
    c.gridwidth = 2;
    replace_dialog.add(replace_label, c);
    c.gridx++;
    c.fill = GridBagConstraints.HORIZONTAL;
    c.weightx = 1;
    replace_dialog.add(replace_tf, c);
    c.gridx++;
    c.gridx++;
    c.gridwidth = 1;
    c.fill = GridBagConstraints.HORIZONTAL;
    replace_dialog.add(replaceAll, c);
    replace_dialog.setSize(400,400);
    replace_dialog.setLocationRelativeTo(null);
    replace_dialog.pack();
    replace_dialog.setVisible(true);
    replaceAll.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            text.setText(text.getText().replaceAll(find_tf.getText(), replace_tf.getText()));
        }
    });
}                                       

public static void main(String args[]) {
    try {
        for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
            if ("Nimbus".equals(info.getName())) {
                javax.swing.UIManager.setLookAndFeel(info.getClassName());
                break;
            }
        }
    } catch (ClassNotFoundException ex) {
        java.util.logging.Logger.getLogger(UndoAndRedoAction.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (InstantiationException ex) {
        java.util.logging.Logger.getLogger(UndoAndRedoAction.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (IllegalAccessException ex) {
        java.util.logging.Logger.getLogger(UndoAndRedoAction.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    } catch (javax.swing.UnsupportedLookAndFeelException ex) {
        java.util.logging.Logger.getLogger(UndoAndRedoAction.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
    }
    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            new UndoAndRedoAction().setVisible(true);
        }
    });
}

// Variables declaration - do not modify                     
private javax.swing.JMenu fileMenu;
private javax.swing.JMenuBar jMenuBar1;
private javax.swing.JMenuItem open;
private javax.swing.JMenuItem redo;
private javax.swing.JMenuItem replace;
private javax.swing.JMenuItem rollback;
private javax.swing.JTabbedPane tp;
// End of variables declaration                   
}

最佳答案

好的@user3912886,现在我明白你的问题了。 您的问题是打开文件不应该是不可撤消的。 然后您可以先将文本分配到文本区域,然后添加监听器。

    public class UndoAndRedo extends javax.swing.JFrame {


        int i = 0;
        UndoManager undoManager = new UndoManager();

        public UndoAndRedo() {
            initComponents();
            rollback.setEnabled(false);
            redo.setEnabled(false);
        }

        @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">                          
        private void initComponents() {

            tp = new javax.swing.JTabbedPane();
            jMenuBar1 = new javax.swing.JMenuBar();
            fileMenu = new javax.swing.JMenu();
            open = new javax.swing.JMenuItem();
            rollback = new javax.swing.JMenuItem();
            redo = new javax.swing.JMenuItem();

            setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

            fileMenu.setText("File");

            open.setText("Open");
            open.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    openActionPerformed(evt);
                }
            });
            fileMenu.add(open);

            rollback.setText("Rollback");
            rollback.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    rollbackActionPerformed(evt);
                }
            });
            fileMenu.add(rollback);

            redo.setText("Redo");
            redo.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    redoActionPerformed(evt);
                }
            });
            fileMenu.add(redo);

            jMenuBar1.add(fileMenu);

            setJMenuBar(jMenuBar1);

            javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
            getContentPane().setLayout(layout);
            layout.setHorizontalGroup(
                    layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(tp, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
            );
            layout.setVerticalGroup(
                    layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(tp, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 279, Short.MAX_VALUE)
            );

            pack();
        }// </editor-fold>                        

        private void openActionPerformed(java.awt.event.ActionEvent evt) {
            final JFileChooser jc = new JFileChooser();
            int returnVal = jc.showOpenDialog(UndoAndRedo.this);
            String title;
            File file = null;
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                file = jc.getSelectedFile();
            }
            JTextArea text = new JTextArea();
            if (jc.getSelectedFile() != null) {
                BufferedReader br = null;
                StringBuffer str = new StringBuffer("");
                try {
                    br = new BufferedReader(new FileReader(file));
                    String line;
                    while ((line = br.readLine()) != null) {
                        str.append(line + "\n");
                    }
                } catch (IOException ex) {
                    Logger.getLogger(UndoAndRedo.class.getName()).log(Level.SEVERE, null, ex);
                }
                String t = str.toString();
                final JInternalFrame internalFrame = new JInternalFrame("", true, true);
                title = file.getName();
                text.setFont(new java.awt.Font("Miriam Fixed", 0, 13));                    
                i += 1;
                internalFrame.setName("Doc " + i);
                JScrollPane scrollpane = new JScrollPane(text);
                internalFrame.setTitle(title);
                tp.add(internalFrame);
                internalFrame.add(scrollpane);
                internalFrame.setVisible(true);
                text.setText(t);
                text.setCaretPosition(0);
                text.getDocument().addUndoableEditListener(new UndoableEditListener() {
                    @Override
                    public void undoableEditHappened(UndoableEditEvent e) {
                        undoManager.addEdit(e.getEdit());
                        rollback.setEnabled(undoManager.canUndo());
                        redo.setEnabled(undoManager.canRedo());
                    }
                });

            }
        }

        private void rollbackActionPerformed(java.awt.event.ActionEvent evt) {
            rollback.setEnabled(undoManager.canUndo());
            if (undoManager.canUndo()) {
                undoManager.undo();
            }
            rollback.setEnabled(undoManager.canUndo());
            redo.setEnabled(undoManager.canRedo());
        }

        private void redoActionPerformed(java.awt.event.ActionEvent evt) {
            redo.setEnabled(undoManager.canRedo());
            if (undoManager.canRedo()) {
                undoManager.redo();
            }
            rollback.setEnabled(undoManager.canUndo());
            redo.setEnabled(undoManager.canRedo());
        }

        public static void main(String args[]) {
            try {
                for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                    if ("Nimbus".equals(info.getName())) {
                        javax.swing.UIManager.setLookAndFeel(info.getClassName());
                        break;
                    }
                }
            } catch (ClassNotFoundException ex) {
                java.util.logging.Logger.getLogger(UndoAndRedo.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            } catch (InstantiationException ex) {
                java.util.logging.Logger.getLogger(UndoAndRedo.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            } catch (IllegalAccessException ex) {
                java.util.logging.Logger.getLogger(UndoAndRedo.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            } catch (javax.swing.UnsupportedLookAndFeelException ex) {
                java.util.logging.Logger.getLogger(UndoAndRedo.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
            }
            java.awt.EventQueue.invokeLater(new Runnable() {
                public void run() {
                    new UndoAndRedo().setVisible(true);
                }
            });
        }
        private javax.swing.JMenu fileMenu;
        private javax.swing.JMenuBar jMenuBar1;
        private javax.swing.JMenuItem open;
        private javax.swing.JMenuItem redo;
        private javax.swing.JMenuItem rollback;
        private javax.swing.JTabbedPane tp;
    }

关于java - 如何使用 Swing 实现撤消和重做操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26583586/

相关文章:

java - 如何查询maven私服中的所有依赖?

java - 外部 JPanle 不显示在 JFrame 上

ios - 核心数据撤消/重做 - 操作取决于撤消的内容

c++ - 撤消历史记录的问题(QUndoStack、QUndoView 和其他)

java - 我可以在前一个的 onanimationEnd 回调中启动一个 Android 动画吗?

java - Hadoop - 连接到 JobTracker

java - 我怎样才能让这个方法在我的循环中更新GUI?

java - 隐藏面板时丢失 JDialog 标题 (Java)

cocoa - 无法从 NSTextField 成功注册撤消

java - 支持 XEP-133 的 XMPP 库(管理员命令)