【问题标题】:How to scale basic drawings?如何缩放基本图纸?
【发布时间】:2019-09-17 14:08:21
【问题描述】:

我想要一个显示在我的窗口中的形状列表。每当我改变窗口的大小时,我都想缩放我的所有图纸。

我已经准备好了类,这些类将关于随机形状的信息存储在一个列表中(矩形、椭圆形等)。我把它们都画出来没有问题,但我无法处理缩放问题。我的解决方案不会改变任何东西,或者使所有形状都消失。

public class Shape extends JPanel{
    int x, y,width,height,red,green,blue;
    double scX, scY; //scale x and y

    public Shape(int x, int y, int width, int height, int red, int green, int blue) {
//...long constructor
        scX=1;
        scY=1;
    }
    void randomizeValues(){...}

        void setScale(double x, double y) {
        this.scX = x;
        this.scY = y;
    }
}

public class Rectangle extends Shape{

    public Rectangle(int x, int y, int width, int height, int red, int green, int blue) {
        super(x, y, width, height, red, green, blue);
    }

    @Override
    protected void paintComponent(Graphics graphics) {
        super.paintComponent(graphics);
        graphics.fillRect((int)(x*scX), (int)(y*scY), (int)(width*scX), (int)(height*scY));
    }
}


class Window extends JFrame {

    int defaultWidth = 768;
    int defaultHeight = 512;
    List<Shape> paintList = new ArrayList<>();

 public Window() {
        setTitle("Shape");
        add(new DrawShape);
        setSize(defaultWidth, defaultHeight);
        setVisible(true);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    }

class DrawShape extends JPanel {
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            for (int i = 0; i< paintList.size(); i++) {
                Shape s = paintList.get(i);
                s.setScale(this.getWidth()/defaultWidth, this.getHeight()/defaultHeight);
                s.paintComponent(g);
            }
   }
}

如何制作适当的比例技巧?我应该在哪里乘以值,以使一切正常运行?

【问题讨论】:

  • s.paintComponent(g); - 不,不要这样做,你没有任何理由应该直接调用组件paint 方法。相反,设计一个或多个执行所需操作的类(即Box,它不从组件扩展,它有一个“绘制”方法,您可以通过它传递Graphics 上下文)
  • This demonstrates the use of AffineTransform#scale 在处理基于像素的渲染时可用于缩放Graphics 上下文。一个“更好”的解决方案是缩放各个形状的坐标,这在here 中得到了证明
  • 如果您想查看基于窗口大小的解决方案缩放,您可以查看this example
  • 您正在为自己的类使用诸如 Shape、WIndow 和 Rectangle 之类的名称,这些名称已经在 J​​ava API 中定义(其中 Shape 是一个接口)。为避免混淆,您应该更改这些。您还应该查看 Java 教程中的 Custom Painting

标签: java arrays list jpanel awt


【解决方案1】:

首先,您不应该将 JPanel 添加到窗口中,而是将其设置为 ContentPane:setContentPane(new DrawShape());。接下来,您不应该在循环内部重绘,而是在外部重绘(例如在 paintComponent(Graphics g) 方法的末尾)。这样,JPanel 应该被永久地再次绘制。 如果您需要根据窗口尺寸更改形状的大小,请在您的 JPanel paintComponent(Graphics g) 方法中执行此操作:

//fill it with the shapes base sizes (index 0 = width, index 1 = height)
Map<Shape,int[]> shapeSizes = new HashMap<Shape,int[]>();
public void paintComponent(Graphics g) {
double widthCoeff = this.getWidth()/(double)Window.this.defaultWidth;
double heightCoeff = this.getHeight()/(double)Window.this.defaultHeight;
for (int i = 0; i< paintList.size(); i++) {
Shape s = paintList.get(i);
int[] baseSize = shapeSizes.get(s);
int oldWidth = baseSize[0], oldHeight = baseSize[1];
int width = oldWidth*widthCoeff, height = oldHeight*heightCoeff;
//you can now give the shape its new width and height
}
}

【讨论】:

  • 感谢您的建议。你能告诉我,如果在循环中调用 listElement(i).paintComponent() 是一个糟糕的举动,我应该如何绘制列表中的每个形状?
  • 我建议将您的Shape 对象转换为Polygons(由Java API 定义),这样您就可以通过调用g.drawPolygon(polygon); 进行绘制。
  • "首先,您不应该将 JPanel 添加到窗口中,而是将其设置为 ContentPane : setContentPane(new DrawShape());" 从 Java 1.6 开始,@ 987654328@ 自动转发到contentPane
猜你喜欢
  • 2012-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多