【问题标题】:How to support and paint multiple algorithms如何支持和绘制多种算法
【发布时间】:2021-12-01 17:47:38
【问题描述】:

我一直在研究迷宫生成器/求解器程序。它运行良好,但我在重构代码时遇到了问题。

基本上,我过去常常调用直接从另一个类中绘制解决迷宫过程的方法,而不是调用paintComponent 方法(或者更确切地说是repaint 方法)。显然这不是一个好的做法,在性能方面也不是令人满意的,我正试图解决这个问题。

问题是,要绘制解决方案的子步骤,不同的求解器算法需要不同类型和数量的参数。 我可以将它们存储在一个类中,然后调用 paintComponent 方法,在该方法中我调用使用上述参数绘制子步骤的方法。

不幸的是,这意味着我必须创建一堆扩展 JPanel 的其他类,这样我就可以存储必要的集合和变量,这样我就可以得出一个特定的解决方案。

有没有更好的方法来解决这个问题,还是我应该放弃并按照我提到的方式去做?

所以我想做什么:

@Override
public void paintComponent(Graphics g){
    super(g);
    drawMaze(g);
    switch(solverType) //Based on what solver is assigned to the maze it calls the proper method
    {
       case solver1:
          solver1Drawer(g, additional arguments);
       break;
       case solver2:
          solver2Drawer(g, different kind, and number of arguments);
       break;
       //Other cases, with other method calls
    }
}

【问题讨论】:

  • 退后一步。考虑paintComponent 方法的职责,它的工作是什么?它的工作是绘制组件的当前状态,它并不是真的要执行这样的复杂逻辑。还要考虑这样一个事实,即paintComponent 可以出于多种原因随时调用,其中许多原因是您无法控制的,您需要仔细计划paintComponent。相反,您的“求解器”应该充当“模型”,向组件提供信息以允许其确定表示它们包含的数据的最佳方式,这是 MVC 的基础

标签: java swing path-finding maze custom-painting


【解决方案1】:

有很多方法可以构建可以接受不同求解器和视图的此类应用程序。我将尝试演示一个非常基本的、精简的,以使其尽可能简单。
为此,我们将使用一个求解器来计算某个形状的周长并绘制解。
首先,我们将定义一些接口,稍后会更清楚地了解它们的使用:

interface Model{
    boolean solve();
    int solution();
    boolean isSolved();
}

interface View{
    void draw(Graphics g);
}

interface Solver {
    Model getModel();
    View getView();
}

使用这些接口,我们将定义 Model、View 和 C控制器以支持计算周长一个正方形。
模型封装了信息(属性和状态)和逻辑:

class SquarePrimeterModel implements Model{

    private final int edgeLength;
    private int perimeter;
    private boolean isSolved = false;

    public SquarePrimeterModel(int edgeLength) {
        this.edgeLength = edgeLength;
    }

    @Override
    public boolean solve() {
        perimeter = 4 * edgeLength;
        isSolved = true;
        return true;
    }

    @Override
    public int solution() {
        return perimeter;
    }

    @Override
    public boolean isSolved() {
        return isSolved;
    }

    //edgeLength is a unique property for this model
    public int getEdgeLength() {
        return edgeLength;
    }
}

视图的职责,顾名思义就是生成视图:

class SquarePrimeterView implements View{

    private final static int xOffset = 50, yOffset = 50, GAP = 20;
    private final SquarePrimeterModel model;

    public SquarePrimeterView(SquarePrimeterModel model) {
        this.model = model;
    }

    @Override
    public void draw(Graphics g) {
        if(model.isSolved()){
            g.drawRect(xOffset, yOffset, model.getEdgeLength(), model.getEdgeLength());
            String text = "Edge =" + model.getEdgeLength() + " Perimiter ="+ model.solution();
            int yPosition = yOffset + model.getEdgeLength()+ GAP;
            g.drawString(text, xOffset, yPosition);
        }
    }
}

控制器构建、配置和管理模型和视图:

class SquarePrimeterController implements Solver{

    private final SquarePrimeterModel model;
    private final View view;

    public SquarePrimeterController(int edgeLength) {
        model = new SquarePrimeterModel(edgeLength);
        view = new SquarePrimeterView(model);
    }

    @Override
    public Model getModel() {
        return model;
    }

    @Override
    public View getView() {
        return view;
    }
}

如果我们需要另一个求解器,例如计算三角形周长的求解器,我们只需编写与 SquarePrimeter 类非常相似的 TriangelPrimeterController、TriangelPrimeterModel 和 TriangelPrimeterView。

我们需要的最后一段代码是使用SquarePrimeterController的应用程序:

public class SwingMVCSolveController {

    public SwingMVCSolveController() {
        Solver solver = new SquarePrimeterController(150);//todo: select solver by gui 
        solver.getModel().solve(); //todo start solve by gui 
        new MainView(solver.getView());
    }

    public static void main(String[] args) {
        new SwingMVCSolveController();
    }
}

class MainView extends JPanel {

    private static final Dimension size = new Dimension(400, 400);
    private final View solverView;
    public MainView(View view) {
        solverView = view;
        createAndShowGui();
    }

    private void createAndShowGui() {
        JFrame frame = new JFrame ();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.add (this);
        frame.pack();
        frame.setVisible (true);
    }

    @Override
    public Dimension getPreferredSize() {
        return size;
    }

    @Override
    protected void paintComponent(Graphics g){
        super.paintComponent(g);
        solverView.draw(g);
    }
}

显然Solver solver = new SquarePrimeterController(150); 可以更改为Solver solver = new TrianglePrimeterController(150);Solver 的任何其他实现。

完整的可运行代码可用here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-16
    相关资源
    最近更新 更多