绘制策略包详细解析
Strategy类
Strategy类是所有绘图策略类的父类,绘图策略类是采用了策略模式的设计模式,思想是根据用户绘图的选择,把画布和输入的处理委托给一个策略实例来执行,而用户更换选择时,只需要更换具体的策略即可,不需要对程序进行修改。
- Strategy类字段一览表
修饰符 | 类型 | 名称 | 说明 |
---|---|---|---|
protected | Editor | editor | 策略类所要处理的主程序 |
protected | SafeKeyboardInput | keyboard | 策略类需要处理的键盘输入 |
protected | RelativeMouseInput | mouse | 策略类需要处理的鼠标输入 |
protected | ArrayList< ImageElement> | elements | 策略类可以直接对将要绘制的元素进行更改 |
protected | Color | color | 当前绘图颜色,默认值为黑色 |
protected | boolean | drawing | 当前是否开始绘制,默认值为false |
- Strategy类方法一览表
修饰符 | 返回值 | 函数名 | 参数 | 说明 |
---|---|---|---|---|
public | Strategy | (Editor editor,SafeKeyboardInput keyboard,RelativeMouseInput mouse,ArrayList< ImageElement> elements) | 构造函数 | |
public | void | setColor | (Color color) | 设置当前绘制的颜色 |
public | void | finishDrawing | () | 完成一个图形的绘制后需要调用的处理操作 |
proteted | void | goBackForOneStep | () | 撤销一步操作,移除图形元素列表最顶端的一个非空元素 |
public | void | processInput | () | 处理输入,先处理撤销操作,再处理绘制操作 |
proteted abstract | void | process | () | 处理输入进行绘制操作 |
proteted | void | jump | (Vector2f mousePos) | 快捷选择到某位置之后的操作 |
public | void | similar | (Vector2f mousePos,Matrix3x3f view) | 快捷选择到某位置 |
- Strategy类源代码
package Rendering.strategy;
import Rendering.Editor;
import Rendering.element.ImageElement;
import Rendering.element.Points;
import Rendering.utils.Matrix3x3f;
import Rendering.utils.RelativeMouseInput;
import Rendering.utils.SafeKeyboardInput;
import Rendering.utils.Vector2f;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
public abstract class Strategy {
protected Editor editor;
protected SafeKeyboardInput keyboard;
protected RelativeMouseInput mouse;
protected ArrayList<ImageElement> elements;
protected Color color;
protected boolean drawing;
public Strategy(Editor editor,
SafeKeyboardInput keyboard,
RelativeMouseInput mouse,
ArrayList<ImageElement> elements) {
this.editor = editor;
this.keyboard = keyboard;
this.mouse = mouse;
this.elements = elements;
this.color = Color.BLACK;
this.drawing = false;
}
public void setColor(Color color) {
this.color = color;
}
public void finishDrawing() {
drawing = false;
}
protected void goBackForOneStep() {
if (mouse.buttonDownOnce(MouseEvent.BUTTON3) && elements.size() > 0) {
finishDrawing();
ImageElement tmp = elements.remove(elements.size() - 1);
while (elements.size() > 0 && tmp.empty()) {
tmp = elements.remove(elements.size() - 1);
}
if (tmp instanceof Points) {
tmp = ((Points) tmp).remove();
if (!tmp.empty()) {
elements.add(tmp);
}
} else if (tmp instanceof FillPolygon) {
if (((FillPolygon) tmp).removePoint()) {
if (!tmp.empty()) {
elements.add(tmp);
if (this instanceof FillPolygonStrategy) {
((FillPolygonStrategy) this).polygon = (FillPolygon) tmp;
((FillPolygonStrategy) this).drawing = true;
}
}
}
}
}
}
public void processInput() {
goBackForOneStep();
process();
}
protected abstract void process();
protected void jump(Vector2f mousePos) {}
public void similar(Vector2f mousePos, Matrix3x3f view) {
mouse.moveMouse(view.mul(mousePos));
jump(mousePos);
}
}
NullStrategy类
NullStrategy类是一个对输入不做任何处理的类。适用于对图像的观察模式,无法对当前绘制的图形做任何修改。
- NullStrategy类源代码
package Rendering.strategy;
import Rendering.Editor;
import Rendering.element.ImageElement;
import Rendering.utils.RelativeMouseInput;
import Rendering.utils.SafeKeyboardInput;
import java.util.ArrayList;
public class NullStrategy extends Strategy {
public NullStrategy(Editor editor,
SafeKeyboardInput keyboard,
RelativeMouseInput mouse,
ArrayList<ImageElement> elements) {
super(editor, keyboard, mouse, elements);
}
@Override
protected void goBackForOneStep() {}
@Override
public void process() {}
}
PointsStrategy类
PointsStrategy类是对点列的绘制策略,继承了Strategy类。新增Points字段,代表当前绘制的点列实例;重写了setColor和process方法,使其适用于对点列的绘制。
- PointsStrategy类源代码
package Rendering.strategy;
import Rendering.Editor;
import Rendering.element.ImageElement;
import Rendering.element.Points;
import Rendering.utils.RelativeMouseInput;
import Rendering.utils.SafeKeyboardInput;;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
public class PointsStrategy extends Strategy {
protected Points points;
public PointsStrategy(Editor editor,
SafeKeyboardInput keyboard,
RelativeMouseInput mouse,
ArrayList<ImageElement> elements) {
super(editor, keyboard, mouse, elements);
}
@Override
public void setColor(Color color) {
super.setColor(color);
points = new Points(this.color);
elements.add(points);
}
@Override
public void process() {
if (elements.size() < 1 || elements.get(elements.size() - 1) != points) {
points = new Points(this.color);
elements.add(points);
}
if (mouse.buttonDownOnce(MouseEvent.BUTTON1)) {
drawing = true;
}
if (mouse.buttonDown(MouseEvent.BUTTON1)) {
points.addPoint(editor.getWorldMousePosition());
} else if (drawing) {
points.addPoint(null);
drawing =false;
}
}
}
BeginEndStrategy类
BeginEndStrategy类继承了Strategy类,是对所有的可以通过起点拖动到终点绘制的图形元素的一种绘制策略。除了新增两个字段表示起点和终点,重写了finishDrawing,process和jump方法以适应快捷选择操作之外,还新增了以下3个对于拖动绘制的图形通用的方法。
- protected abstract void addElement():添加一个图形元素。
- protected void removeElement():移除顶层图形元素。
- protected void updateElement():每帧更新图形元素。
其中addElement方法在实际使用时需要根据具体绘制的图形来进行重写。
- BeginEndStrategy类源代码
package Rendering.strategy;
import Rendering.Editor;
import Rendering.element.ImageElement;
import Rendering.utils.Matrix3x3f;
import Rendering.utils.RelativeMouseInput;
import Rendering.utils.SafeKeyboardInput;
import Rendering.utils.Vector2f;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
public abstract class BeginEndStrategy extends Strategy {
protected Vector2f begin;
protected Vector2f end;
public BeginEndStrategy(Editor editor,
SafeKeyboardInput keyboard,
RelativeMouseInput mouse,
ArrayList<ImageElement> elements) {
super(editor, keyboard, mouse, elements);
}
@Override
public void finishDrawing() {
super.finishDrawing();
begin = null;
end = null;
}
protected abstract void addElement();
protected void removeElement() {
elements.remove(elements.size() - 1);
}
protected void updateElement() {
removeElement();
addElement();
}
@Override
public void process() {
if (mouse.buttonDownOnce(MouseEvent.BUTTON1) && begin == null) {
drawing = true;
begin = editor.getWorldMousePosition();
end = editor.getWorldMousePosition();
addElement();
mouse.poll();
}
if (drawing) {
end = editor.getWorldMousePosition();
updateElement();
}
if (mouse.buttonDownOnce(MouseEvent.BUTTON1) && begin != null) {
finishDrawing();
}
}
@Override
protected void jump(Vector2f mousePos) {
if (begin == null) {
drawing = true;
begin = mousePos;
end = mousePos;
addElement();
mouse.poll();
} else {
end = mousePos;
updateElement();
finishDrawing();
}
}
}
FillPolygonStrategy类
FillPolygonStrategy类继承了Strategy类,是填充多边形的绘制策略类。与BeginEndStrategy类具有类似的绘制策略,但由于输入的处理策略不同,不能继承自BeginEndStrategy类。
- FillPolygonStrategy类源代码
package Rendering.strategy;
import Rendering.Editor;
import Rendering.element.FillPolygon;
import Rendering.element.ImageElement;
import Rendering.utils.RelativeMouseInput;
import Rendering.utils.SafeKeyboardInput;
import Rendering.utils.Vector2f;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
public class FillPolygonStrategy extends Strategy {
protected FillPolygon polygon;
public FillPolygonStrategy(Editor editor,
SafeKeyboardInput keyboard,
RelativeMouseInput mouse,
ArrayList<ImageElement> elements) {
super(editor, keyboard, mouse, elements);
}
@Override
public void setColor(Color color) {
super.setColor(color);
if (polygon != null) {
polygon = new FillPolygon(polygon, this.color);
updateElement();
}
}
protected void addElement() {
elements.add(polygon);
}
protected void removeElement() {
elements.remove(elements.size() - 1);
}
protected void updateElement() {
removeElement();
addElement();
}
@Override
public void finishDrawing() {
super.finishDrawing();
polygon = null;
}
@Override
public void process() {
if (mouse.buttonDownOnce(MouseEvent.BUTTON1) &&
(polygon == null || (polygon != null && polygon.isClosed()))) {
drawing = true;
polygon = new FillPolygon(color);
polygon.addPoint(editor.getWorldMousePosition());
addElement();
mouse.poll();
keyboard.flush();
}
if (mouse.buttonDownOnce(MouseEvent.BUTTON1) && drawing) {
polygon.addPoint(editor.getWorldMousePosition());
updateElement();
mouse.poll();
keyboard.flush();
}
while (keyboard.processEvent()) {
if (keyboard.keyDownOnce(KeyEvent.VK_C)) {
updateElement();
polygon.close();
finishDrawing();
}
}
}
@Override
protected void jump(Vector2f mousePos) {
super.jump(mousePos);
if (polygon == null || (polygon != null && polygon.isClosed())) {
drawing = true;
polygon = new FillPolygon(color);
polygon.addPoint(mousePos);
addElement();
mouse.poll();
keyboard.flush();
} else {
polygon.addPoint(mousePos);
updateElement();
mouse.poll();
keyboard.flush();
}
}
}
StringStrategy类
StringStrategy类继承了Strategy类,是字符串的绘制策略类。和FillPolygonStrategy类一样,虽然与BeginEndStrategy类具有类似的绘制策略,但由于输入的处理策略不同,不能继承自BeginEndStrategy类。
- StringStrategy类源代码
package Rendering.strategy;
import Rendering.Editor;
import Rendering.element.ImageElement;
import Rendering.element.StringElement;
import Rendering.utils.RelativeMouseInput;
import Rendering.utils.SafeKeyboardInput;
import Rendering.utils.Vector2f;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
public class StringStrategy extends Strategy {
protected Vector2f position;
protected StringBuffer message;
public StringStrategy(Editor editor,
SafeKeyboardInput keyboard,
RelativeMouseInput mouse,
ArrayList<ImageElement> elements) {
super(editor, keyboard, mouse, elements);
}
@Override
public void finishDrawing() {
super.finishDrawing();
position = null;
message = null;
}
protected void addElement() {
elements.add(new StringElement(position, message.toString(), color));
}
protected void removeElement() {
elements.remove(elements.size() - 1);
}
protected void updateElement() {
removeElement();
addElement();
}
@Override
public void process() {
if (mouse.buttonDownOnce(MouseEvent.BUTTON1) && position == null) {
drawing = true;
position = editor.getWorldMousePosition();
message = new StringBuffer().append("");
addElement();
mouse.poll();
keyboard.flush();
}
if (drawing) {
while (keyboard.processEvent()) {
Character tmpChar = keyboard.getKeyTyped();
if (tmpChar != null) {
if (Character.isISOControl(tmpChar)) {
if (KeyEvent.VK_BACK_SPACE == tmpChar
&& message.length() > 0) {
message.deleteCharAt(message.length() - 1);
}
} else {
message.append(tmpChar);
}
}
}
updateElement();
}
if (mouse.buttonDownOnce(MouseEvent.BUTTON1) && position != null) {
finishDrawing();
}
}
@Override
protected void jump(Vector2f mousePos) {
super.jump(mousePos);
if (position == null) {
drawing = true;
position = mousePos;
message = new StringBuffer().append("");
addElement();
mouse.poll();
keyboard.flush();
}
}
}
更多: