使用MVC绘制同心/旋转图形

时间:2014-07-12 13:34:26

标签: java swing model-view-controller jpanel draw

正如标题中所提到的,我试图使用MVC将旋转和/或同心图形绘制到面板上。这些数字是Circles,Ellipses和Astroids。

我得到了我应该在任务描述中使用的参数方程式:

    x = r_x * cos^power(phi * PI/180) and y = r_y * sin^power(phi * PI/180).   

圆圈/椭圆的功率为1(因此是正常的cos / sin),星形的功率为3。

我也应该使用MVC来解决这个问题,这对我来说有点新鲜,所以有时候我不确定我是否可以做某事或者不应该这样做,以免我违反MVC角色。 Phi用于计算圆(或椭圆)上的某个点,因此可用于计算3,4,5等点,绘制三角形,正方形,五边形等。

我设法使用上面的公式计算和绘制简单的数字。 我现在面临的问题是旋转和/或使它们同心。

这是我现在正在使用的代码(重要部分):

DescView(主要是设置按钮,标签等基本内容)

public DescView(){      
    model = new DescModel();
    createGUI(); // creates and sets up the frame
    createCanvas(); // creates the Panel which is drawn upon(own Class, see below)
    createChoiceStuff(); // creates Buttons, Labels, Textfields for Choices
    createPanels(); // creates and places the Panel for Choices
    addContentToPanels(); // adds the Buttons etc to the Panel
    frame.setVisible(true);

    controller = new DescController(model, this);
}

Canvas(内部类到DescView):

class Canvas extends JPanel{

    DescModel model;
    int temp = 0;

    public Canvas(DescModel _model){
        this.model = _model;
    }

    public void paintComponent(Graphics _graphics){
        super.paintComponent(_graphics);


        //First while loop: Used to prevent drawing when Points is Empty
        //which it always is when the program starts.
        while(!model.getPoints().isEmpty()){
            //second loop: Keeps drawing a Line using a Collection(Points) until
            //the last element would go out of bounds.
            //drawLine takes the first 4 Elements from Points, then the 2,3,4,5
            //and so on.
            while(3 + temp < model.getPoints().size()){
                _graphics.drawLine(model.getPoints().get(0 + temp), model.getPoints().get(1 + temp), model.getPoints().get(2 + temp), model.getPoints().get(3 + temp));
                temp += 2;
            }
            //drawing the last Line from the two last Points to the first two
            _graphics.drawLine(model.getPoints().get(model.getPoints().size() - 2), model.getPoints().getLast(), model.getPoints().getFirst(), model.getPoints().get(1));

            //resetting temp and Points so they can be used again
            temp = 0;
            model.getPoints().clear();
        }               
    }   

DescController

public class DescController implements ActionListener {

    DescModel model;
    DescView view;

    DescController(DescModel _model, DescView _view){       
         this.model = _model;
         this.view = _view;

        view.addViewListener(this); 
    }

    @Override
    public void actionPerformed(ActionEvent ae) {
        //asks the model to calculate a circle(or a part of it, depending on degree = phi)
        //as you can see, Cirlce and Ellipse doe the same(which is good), unless RadiusX
        //and RadiusY are different. After the calculation the Canvas is oredered to
        //repainted
        if(ae.getSource() == view.getBtCirlce()){
            model.calcNumbers(Integer.parseInt(view.getTfRadiusX().getText()), Integer.parseInt(view.getTfRadiusY().getText()), 1, Integer.parseInt(view.getTfDegree().getText()));     
            view.getCanvas().repaint();
        }
        else if(ae.getSource() == view.getBtEllipse()){
            model.calcNumbers(Integer.parseInt(view.getTfRadiusX().getText()), Integer.parseInt(view.getTfRadiusY().getText()), 1, Integer.parseInt(view.getTfDegree().getText()));
            view.getCanvas().repaint();
        }
        else if(ae.getSource() == view.getBtAstroid()){
            model.calcNumbers(Integer.parseInt(view.getTfRadiusX().getText()), Integer.parseInt(view.getTfRadiusY().getText()), 3, Integer.parseInt(view.getTfDegree().getText()));         
            view.getCanvas().repaint();
        }
        else if(ae.getSource() == view.getBtInfo()){
            view.showInfo();
        }
        else if(ae.getSource() == view.getBtQuit()){
            System.exit(0);
        }
    }
}

DescModel

public class DescModel {
    int x = 1;
    int y = 1;

    LinkedList<Integer> points = new LinkedList<Integer>();

    public DescModel() {
    }
    //calculates X and Y coordinates one by one. Phi is used to calculate only a
    //certain number of points. For example for phi = 90 a Square is drawn
    //and a full circle for phi = 1 (if X = Y).
    //addOffset is used to place the figure in the middle of Canvas, which
    //has a width and height of 600.
    public void calcNumbers(int _radiusX, int _radiusY, int _potenz, int _phi){
        for(int i = 1; i <= 360 / _phi; i++){
            calcX(_radiusX, _potenz, _phi * i);
            calcY(_radiusY, _potenz, _phi * i);
        }
        addOffset();
    }   
    //Calculates using the above formula and adds the point to the Collection
    private void calcX(int _radiusX, int _potenz, int _phi){
        x = 300 + (int)(_radiusX * Math.pow(Math.cos(_phi * (Math.PI / 180)), _potenz));
        addToPoints(x);
    }

    private  void calcY(int _radiusY, int _potenz, int _phi){
        y = 300 + (int)(_radiusY * Math.pow(Math.sin(_phi * (Math.PI / 180)), _potenz));
        addToPoints(y);
    }

    private void addOffset(){
        for(int i = 0; i < points.size(); i++){
        }
    }

    private void addToPoints(int _number){
        points.add(_number);
    }
}

现在接下来我想要/必须做的是允许选择以固定半径旋转并同心绘制相同的东西。 显然,我可以使用较小的参数运行相同的model.calcNumbers()。但是,我不确定我能做到这一点,因为视图不应该直接调用模型吗?即使这是允许的,如果我要重新打电话,旧圈子也会消失。 使用相同的数组也不会起作用,因为那时我会绘制圆圈,它们都有一条连接它们的线。 关于旋转,我可能会为每个点添加一定值,然后再次绘制它。我怎么会去那个绘图部分呢?与同心相同的问题:旧图片将消失。

提前感谢您的帮助。

编辑:因为似乎有些混乱:我不需要动画这个。它足以拥有一组形状。例如:绘制一个半径为100的圆,另一个半径为90的圆,其次是半径80等。

旁注:这是我的第一个问题,所以有关格式化,更好地制定问题等的提示当然是受欢迎的。

1 个答案:

答案 0 :(得分:1)

这个AnimationTest说明了使用更简单的参数方程的基本方法。对于轮换,您可以使用AffineTransform,如herehere所示。最后,这个answer详细说明了Swing如何使用MVC模式。