Материал: Портянкин И. Swing

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

590

ГЛАВА 18

JPanel buttons = new JPanel(); buttons.add(add); buttons.add(undo); buttons.add(redo); add(buttons, "South");

// выведем окно на экран setSize(400, 300); setVisible(true);

}

// класс, описывающий добавление в список

class ListAddUndoableEdit extends AbstractUndoableEdit { // модель и новый элемент

private DefaultListModel model; private Object element;

public ListAddUndoableEdit(DefaultListModel model, Object element) {

this.model = model; this.element = element;

}

@Override

public void undo() throws CannotUndoException { super.undo();

model.removeElement(element);

}

@Override

public void redo() throws CannotRedoException { super.redo();

model.addElement(element);

}

}

public static void main(String[] args) { SwingUtilities.invokeLater(

new Runnable() {

public void run() { new UndoListAdd(); } });

}

}

В примере в центре окна разместятся два списка одинакового размера. У них будет одна стандартная модель DefaultListModel, поначалу пустая. На юге окна у нас разместится панель с последовательным расположением, с тремя кнопками. Первая кнопка будет добавлять к модели новый элемент, вторая отменять последнюю операцию, а третья повторять отмененную операцию. Для того чтобы класс UndoManager смог работать с нашей операцией, необходимо описать ее с помощью интерфейса UndoableEdit. Он довольно громоздкий, поэтому проще воспользоваться абстрактным классом AbstractUndoableEdit,

Круговорот данных

591

в котором уже многое реализовано, что мы и делаем. В конструктор операции следует передать стандартную модель списка и новый элемент. В общем же требуется лишь описать методы undo() и redo(), в которых мы удаляем новый элемент или заново добавляем его. Все довольно очевидно, есть лишь одна деталь — необходимо вызвать метод базового класса, так как он должен знать, когда мы отменили или повторили операцию, чтобы затем класс UndoManager смог узнать, доступна ли в данный момент отмена или повтор.

Когда изменение данных описано в требуемом виде, остается регистрировать его

вобъекте UndoManager в момент изменения, что мы и делаем методом addEdit(). Оставшееся является делом техники — кнопки отмены и повтора операций просто вызывают методы undo() и redo() для объекта UndoManager, предварительно удостоверившись

втом, что это возможно, методами canUndo() и canRedo(). Запустив пример, вы убедитесь

втом, что отмена и повтор операций работает на обоих списках, и при этом стандартная модель сама оповещает их об изменениях, а непосредственно изменения работают только с данными, ничего не зная о том, какие графические компоненты и где их отображают.

Это лишь начальный пример, и отталкиваясь от данных и моделей, мы сможем легко встроить в приложение отмену и повтор любых операций, причем на гибкости приложения и легкости изменения его графического интерфейса это никак не должно отразиться. Отделение данных от их отображения и деталей прорисовки на экране всегда платит сторицей в виде надежных и практичных приложений.

Резюме

Хотя обмен данными с другими приложениями системы или внутри единственного приложения, а также поддержка отмены случайных изменений в этих данных уже косвенно относятся к Swing и графическим компонентам, библиотека предоставляет весь арсенал, необходимый для реализации этих возможностей. Если в случае обмена данными за нас многое сделано и встроено на самом базовом уровне компонента JComponent, то при отмене и повторе изменений у нас есть лишь легкий фундамент UndoManager, который, тем не менее, является хорошей отправной точкой.

Источник: https://studfile.net/preview/15935977/