使用撤消/ Swing中重做一个MVC模式?(using undo/redo in Swing fo

2019-10-17 07:01发布

我有一个MVC模型,我试着去撤销/重做的功能添加到它。 用户可以将一些在一个JTextField,当他们点击撤销按钮,它应该被删除。 我所提供的代码为我的类实现此。 我得到的错误是在底部。

控制包:

ButtonnGUIControl.java

包控制;

/ ** *这个类将控制GUI.It的按钮动作实现ActionListener()方法*和基于被点击的按钮,它将初始化在模型类的*对应的部件。 * * /

public class ButtonGUIControl implements ActionListener{
private SudokuModel model;
private ButtonGUI bgui;
final UndoManager manager = new UndoManager();



public ButtonGUIControl(SudokuModel model) {
    this.model = model;
}

/*This method will listen for user events, and act accordingly
 * */

public void actionPerformed(ActionEvent e) {
    try {   
         if(e.getActionCommand().equals("Check My Answer!")){

            model.checkGame();
        }


         else if (e.getActionCommand().equals("Undo")){

             try {

                    manager.undo();
                } catch (CannotUndoException ex) { ex.printStackTrace(); }
                finally {
                    //updateButtons();
                }                   
         }
         else if (e.getActionCommand().equals("Redo")){

             manager.redo();
             System.out.println("e.getActionCommand().equals redo");
         }

        //otherwise, it simply places the selected number in the grid
        else{

            model.setNumber(Integer.parseInt(e.getActionCommand()));
        }

    } catch (NumberFormatException e1) {}

    catch (IOException e1) {}
    catch (CannotUndoException ex) {
        System.out.println("Unable to undo: " + ex);
        ex.printStackTrace();
        }
    catch (CannotRedoException ex) {
        System.out.println("Unable to redo: " + ex);
        ex.printStackTrace();
    }    

}

public void undoableEditHappened(UndoableEditEvent evt) {

    manager.addEdit(evt.getEdit());

    //bgui.updateButtons();

}

}


在视图中包:ButtonGUI.java

我添加actionListner的按钮:

RedoBttn.addActionListener(buttonController);

UndoBttn.addActionListener(buttonController);


在Grid.java,它扩展了JTextField中:

public class Grid extends JTextField {
private int x;       
private int y; 

final UndoManager manager = new UndoManager();


public Grid(int x, int y) {
    super("");
    this.x = x;
    this.y = y;
    getDocument().addUndoableEditListener(manager);



    setPreferredSize(new Dimension(40, 40));
    setBorder(BorderFactory.createLineBorder(Color.GREEN));
    setOpaque(true);
}


public void setNumber(int number, boolean userInput)  {


    if(number > 0 & !userInput){
        setText(""+number);
        setEditable(false);


    }

    //These set of numbers are the only ones that the user can undo/redo
    else if (number > 0 & userInput){
        setText(""+number);
        setEditable(true);
}
    else
    setText("");

我在视图包另一类还增加了一个鼠标listenr到每个JTextField的的。 因此,我认为我有撤销/重做结构的权利。 当我运行该程序,我可以选择一个数字,并将其放置在一个JTextField(网格),但只要我打“撤消”我得到以下异常:

    javax.swing.undo.CannotUndoException
at javax.swing.undo.UndoManager.undo(UndoManager.java:411)
at control.ButtonGUIControl.actionPerformed(ButtonGUIControl.java:76)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.Component.processMouseEvent(Component.java:6505)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
at java.awt.Component.processEvent(Component.java:6270)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Component.dispatchEventImpl(Component.java:4861)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Component.dispatchEvent(Component.java:4687)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
at java.awt.Container.dispatchEventImpl(Container.java:2273)
at java.awt.Window.dispatchEventImpl(Window.java:2713)
at java.awt.Component.dispatchEvent(Component.java:4687)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707)
at java.awt.EventQueue.access$000(EventQueue.java:101)
at java.awt.EventQueue$3.run(EventQueue.java:666)
at java.awt.EventQueue$3.run(EventQueue.java:664)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:680)
at java.awt.EventQueue$4.run(EventQueue.java:678)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:677)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

和线76是我打电话:

    manager.undo() 

在try / catch块。

任何想法什么错? 这是我的撤销/重做的实现或其他什么东西?

谢谢!!!

Answer 1:

尝试包装manager.undo(); 像这样:

if(manager.canUndo())
    manager.undo();

我怀疑的默认UndoListener实现JTextField不添加系统更新(即调用。 setText(""+number);到撤消队列) -从UI只更新。

编辑

做一些测试后,似乎setText("")函数并添加索马里发展事务处的UndoManager ,所以这不是你正在运行到这个问题。 这样就可以防止通过确保有任何撤消的行动,撤消错误; 但是,如果你不是在你得到任何撤消的动作UndoManager ,该问题可能发生在其他地方的代码。



Answer 2:

作为替代方案,考虑JFormattedTextField 。 默认情况下, 复位场编辑动作势必ESC键,但你可以绑定的动作所需的另一个关键,说KeyEvent.VK_Z ,如图中如何使用操作 。 对于跨平台的兼容性,使用getMenuShortcutKeyMask()提到这里 。



文章来源: using undo/redo in Swing for an MVC model?