Java 使用MVC绘制同心/旋转图形
正如标题中提到的,我正在尝试使用MVC在面板上绘制旋转和/或同心图形。这些图形是圆、椭圆和星体 我得到了任务描述中应该使用的参数方程:Java 使用MVC绘制同心/旋转图形,java,swing,model-view-controller,jpanel,draw,Java,Swing,Model View Controller,Jpanel,Draw,正如标题中提到的,我正在尝试使用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用于计算
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等点,绘制三角形、正方形、五边形等
我设法用上述公式计算并画出简单的数字。
我现在面临的问题是旋转和/或使它们同心
下面是我现在正在使用的代码(重要部分):
描述视图(主要是设置按钮、标签等基本内容)
画布(要描述视图的内部类):
描述模型
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);
}
}
公共类模型{
int x=1;
int y=1;
LinkedList points=新建LinkedList();
公共模型(){
}
//逐个计算X和Y坐标。φ仅用于计算a
//一定数量的点。例如,对于φ=90,绘制一个正方形
//和一个完整的圆表示φ=1(如果X=Y)。
//AddiS偏移用于将图形放置在画布中间,
//具有600的宽度和高度。
公共空白计算编号(整数半径x、整数半径y、整数波滕兹、整数φ){
对于(int i=1;i这说明了使用更简单的参数方程的基本方法。对于旋转,您可以使用仿射变换,如图所示和所示。最后,这详细说明了Swing如何使用MVC模式。对于我来说,还不完全清楚最后要绘制什么。对象应该设置动画,还是简单地设置动画可以是多个对象,排列成一个圆圈?(顺便说一句:当你发布一个,你通常会很快得到更好的帮助。只需将代码复制粘贴到IDE中并查看当前状态总是很有帮助的…)@Marco13:在整件事的结尾做一个编辑,希望能把它弄清楚。关于mcve:因为我的部分问题是MVC模型(相反,我能做什么,不能做什么),当我需要几个类时,我应该如何创建最少的代码?如果我要发布可用的代码,我必须添加一些东西(比如框架、按钮等)。可能有一种方法可以解决这个问题,尽管我看不到。也许垃圾神的链接已经回答了这个问题。但是我在再次滚动代码时注意到:你不应该调用model.getPoints().clear();
方法中的paintComponent
从“高级”从角度来看,这意味着视图修改了模型,这是不合适的。但更重要的是:paintComponent
可能会被多次调用,目前,它只会在第一次调用时绘制内容。一般来说,paintComponent
方法不应该有任何副作用(也就是说,它不应该更改任何状态)。感谢您对clear()的提示。我可能只需将clear位置更改为calcNUmbers()的模型调用或者别的什么。我不知道这些链接是否会有帮助,我目前正在尝试弄清楚如何处理g2d的东西。尽管这些链接不能解决我的问题,但它们在理解概念、我的选项等方面起到了辩护性的帮助。非常感谢。所以最后,我没有使用g2d。相反,我只使用一个集合来存储每个点。为了当一个新的更小的圆开始时,我在中间加了一个“-1”。此外,我还更改了calcNumbers()的参数,使其也采用两个布尔值,“旋转”和“同心”.根据他们的不同,我调用了不同的计算。这些计算主要是利用for循环来减小半径或改变位置。尽管如此,这些技巧确实有助于了解一般情况下的情况(甚至不知道存在仿射变换)。谢谢你们两位。
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();
}
}
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);
}
}