绘图板程序设计及其具体实现 第六篇

绘制策略包详细解析

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();
        }
    }
}

更多:

第一篇
第二篇
第三篇
第四篇
第五篇
第六篇
第七篇
源代码

猜你喜欢

转载自blog.csdn.net/qq_39384184/article/details/80595064