Java 调整JFrame大小后,如何计算圆形状的X-Y坐标和半径?

Java 调整JFrame大小后,如何计算圆形状的X-Y坐标和半径?,java,swing,awt,Java,Swing,Awt,我正在使用JComponent(AWT/SWING)在JFrame上绘制圆,我想确保当用户调整帧的大小时,会进行某些计算并在屏幕上动态绘制圆(无论它是大、小、向左还是向右移动等)。我实现了ComponentAdapter事件和componentresistized方法,但是我很难想出一些动态的方法。这是我的密码: 循环器类 import javax.swing.JFrame; import java.awt.event.*; public class CircleViewer { pu

我正在使用JComponent(AWT/SWING)在JFrame上绘制圆,我想确保当用户调整帧的大小时,会进行某些计算并在屏幕上动态绘制圆(无论它是大、小、向左还是向右移动等)。我实现了
ComponentAdapter
事件和
componentresistized
方法,但是我很难想出一些动态的方法。这是我的密码:

循环器类

import javax.swing.JFrame;
import java.awt.event.*;

public class CircleViewer
{
    public static void main(String[] args)
    {
        final JFrame frame = new JFrame("Circle Shapes");
        final CirclePanel panel = new CirclePanel();

        // Class for Mouse Listener which implements the necessary interfaces
        class MousePressListener implements MouseListener, MouseMotionListener
        {
            public void mouseClicked(MouseEvent event) { }
            public void mouseEntered(MouseEvent event) { }
            public void mouseExited(MouseEvent event) { }
            public void mouseWheelMoved(MouseWheelEvent event) { }
            public void mouseMoved(MouseEvent event) { }
            public void mousePressed(MouseEvent event) { }

            @Override
            public void mouseDragged(MouseEvent event)
            {
                var x = event.getX();
                var y = event.getY();
                panel.moveTo(x, y);
            }

            @Override
            public void mouseReleased(MouseEvent event)
            {
                panel.finalMove();
            }
        }

        panel.addComponentListener(new ComponentAdapter() {
            public void componentResized(ComponentEvent event)
            {
                panel.frameResizeCalculation(frame.getWidth(), frame.getHeight());
            }
        });

        MousePressListener listener = new MousePressListener();
        panel.addMouseListener(listener);
        panel.addMouseMotionListener(listener);

        frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(panel);
        frame.setVisible(true); 
    }
    public static final int FRAME_WIDTH = 700;
    public static final int FRAME_HEIGHT = 500;
}
环板类

import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JComponent;
import java.util.ArrayList;
import java.awt.Color;
import java.lang.Math;
import java.awt.BasicStroke;
import java.awt.Stroke;

public class CirclePanel extends JComponent
{
    private int mouseX;
    private int mouseY;
    private ArrayList<Circle> circleList;
    private final BasicStroke dashLine = new BasicStroke(1, 
            BasicStroke.CAP_BUTT, 
            BasicStroke.JOIN_BEVEL, 
            0, new float[]{6}, 0);
    private Circle newCircle;
    private final Color newCircleColor = Color.RED;
    private final Color finalCircleColor = Color.BLUE;

    public CirclePanel()
    {
        this.circleList = new ArrayList<Circle>();
        this.mouseX = 0;
        this.mouseY = 0;
    }

    public void moveTo(int x, int y)
    {
        mouseX = x;
        mouseY = y;
        if (newCircle == null)
        {
            newCircle = new Circle(x,y,0);
        }
        else
        {
            int dX = newCircle.get(0) - mouseX;
            int dY = newCircle.get(1) - mouseY;
            newCircle.set(2, (int)Math.sqrt(dX*dX + dY*dY));
        }
        repaint();
    }

    public void finalMove()
    {
        if (newCircle != null)
        {
            circleList.add(newCircle);
            newCircle = null;
            repaint();
        }
    }
    // Do something here and change X-Y coordinates and radius of the circles and finally call repaint() method of Graphics2D
    public void frameResizeCalculation(int width, int height)
    {
        var dX = CircleViewer.FRAME_WIDTH - width;
        var dY = CircleViewer.FRAME_HEIGHT - height;
    }

    public void paintComponent(Graphics g)
    {

        g.setColor(finalCircleColor);
        for (Circle circle : circleList) 
        {

            drawCircle(g, circle);
        }

        Circle c = newCircle;
        if (c != null)
        {
            g.setColor(newCircleColor);
            drawCircle(g, c);

            Graphics2D g2 = (Graphics2D)g.create();
            g2.setStroke(dashLine);
            g2.drawLine(c.get(0), c.get(1), mouseX, mouseY);
            g2.dispose();
        }
    }

    public void drawCircle(Graphics g, Circle c)
    {
        g.drawOval(c.get(0) - c.get(2), c.get(1) - c.get(2), c.get(2) * 2, c.get(2) * 2);
    }
}
进行某些计算并在屏幕上动态绘制圆圈(无论大小、向左或向右移动等)

好的,你需要定义你想发生什么,当帧被调整大小。我们不能告诉你该怎么做

但是,在您担心这些之前,您需要重新构造类,以使动态绘制成为可能

我发现基本代码存在以下问题:

  • 忘掉框架尺寸吧。该尺寸与将在您的CirclePanel中进行的自定义绘制无关。也就是说,圆环面板的大小与框架的大小不同,因为框架大小包括框架边框和标题栏。您的逻辑应该基于面板的大小,而不是框架

  • 在进行自定义绘制时,组件还负责重写
    getPreferredSize()
    方法以返回组件的首选大小。然后在代码中将面板添加到框架中,然后在框架上调用
    pack()
    方法

  • 您将类称为CirclePanel,但扩展了JComponent。为什么?给你的班级取一个正确的名字。如果要扩展JComponent,请调用类CircleComponent。如果要调用类CirclePanel,请扩展JPanel。但是您还需要理解扩展JComponent和JPanel之间的区别。所有Swing组件负责在进行任何绘制之前清除组件的背景。JPanel会自动为您执行此操作,您只需在开始时调用super.paintComponent(…)。JComponent不会清除背景,因此必须通过设置图形对象的颜色来清除背景,然后调用fillRect(0,0,getWidth(),getHeight())来绘制背景

  • 圆形对象应包含绘制自身所需的所有信息。您已经有了x、y和半径值。我建议您还需要一个颜色属性,以便每个圆可以是不同的颜色

  • 然后,圆形对象应该知道如何使用其属性绘制自身。因此,Circle类应该有一个方法,比如说
    draw(Graphics-Graphics)
    。然后使用类的属性绘制椭圆。这意味着paintComponent()方法将调用Circle类的draw(…)方法,您将删除当前拥有的drawOval(…)方法

  • “getter”方法不接受参数。如果您觉得其他类需要知道x、y、radius属性,那么创建getX()、getY()和getRadiout()方法。我建议您不需要get()/set()方法

  • 我建议您首先需要执行上述建议,然后才能使绘画充满活力

    接下来,您不需要将ComponentListener添加到面板中。相反,您需要向CirclePanel类的
    paintComponent(…)
    方法添加逻辑。每次面板大小更改时,都会自动调用paintComponent()方法。基本逻辑是确定绘制每个圆时要使用的“乘数”

    因此,您可以使用
    getPreferredSize()
    方法获得首选宽度,也可以使用面板的
    getWidth()
    方法获得当前大小。所以你的乘数是:

    double multiplierX = getWidth() / getPreferredSize().x;
    
    现在需要将此信息传递给Circle objects draw(…)方法,因此方法签名将变成
    draw(Graphics g,double multiplierX)
    。调用
    drawOval(…)
    方法时,将乘数应用于“x”参数。这将导致圆在调整帧大小时沿水平方向移动

    然后重复上述步骤,使倍增器的圆沿垂直方向移动

    然后需要决定如何影响半径

    double multiplierX = getWidth() / getPreferredSize().x;