【问题标题】:Drawing concentric / rotating figures using MVC使用 MVC 绘制同心/旋转图形
【发布时间】:2014-09-03 00:10:28
【问题描述】:

如标题中所述,我正在尝试使用 MVC 在面板上绘制旋转和/或同心图形。这些图形是圆形、椭圆和星状体。

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

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

描述模型

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 等等。

附带说明:这是我的第一个问题,因此当然欢迎任何关于格式化、更好地制定问题等方面的提示。

【问题讨论】:

  • 对我来说,你到底想画什么并不完全清楚。对象应该是动画,还是应该简单地将多个对象排列成一个圆圈? (顺便说一句:当您发布 stackoverflow.com/help/mcve 时,您通常会很快收到更好的帮助。将代码复制并粘贴到 IDE 中并查看当前状态总是很有帮助的......)
  • @Marco13:在整件事情的最后进行编辑,希望这能说明问题。关于 mcve:由于我的部分问题与 MVC 模型有关(相反,我能用它做什么和不能做什么),当我需要几个类时,我应该如何创建最少的代码?如果我要发布可用的代码,我必须添加 东西(如框架、按钮等)。可能有办法解决这个问题,虽然我看不到。
  • 也许来自垃圾神的链接已经回答了这个问题。但是我在再次滚动代码时注意到了一些事情:您应该NOTpaintComponent 方法中调用model.getPoints().clear();。从“高级”的角度来看,这意味着 view 修改了 model,这是不合适的。但更重要的是:paintComponent 可能会被多次调用,目前它只会在第一次调用时绘制内容。一般来说,paintComponent 方法应该有任何副作用(也就是说,它不应该改变任何状态)。
  • 感谢 clear() 的提示。我可能会简单地将清除位置更改为 calcNUMbers() 或其他东西的模型调用。不知道链接是否会有所帮助,我目前正在尝试弄清楚如何处理 g2d 的东西。虽然即使没有解决我的问题,但他们无疑有助于理解我的概念、选项等,非常感谢。
  • 所以最后我没有用g2d。相反,我只使用一个 Collection 来存储每个点。为了决定一个新的、更小的 Circle 何时开始,我在两者之间添加了一个“-1”。此外,我将 calcNumbers() 的参数更改为也采用两个布尔值,“旋转”和“同心”。根据它们,我然后调用不同的计算。那些大多使用 for 循环来减小半径或改变位置。尽管如此,这些技巧确实有助于了解一般的东西(甚至不知道存在像 AffineTransform 这样的东西)。所以谢谢你们两个。

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


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2013-08-26
    • 2012-03-23
    • 1970-01-01
    • 2011-12-15
    • 1970-01-01
    • 2016-02-27
    • 2011-05-22
    • 1970-01-01
    • 2015-06-18
    相关资源
    最近更新 更多