我试图回答与moving a ball across the screen while changing its color over time相关的问题,但是遇到了一个奇怪的错误(很可能是在我的代码中),在问这个问题时我来到了related question,但是该问题使用的是Client-Server体系结构而我的只是运行自身的Swing应用程序。

发生的情况是,当圆/球(无论您要如何命名)达到JPanelJFrame的一半宽度时,它变得不可见或停止。

起初我以为可能是我的JPanel位置不正确,但是我给它添加了Border,所以我可以看到它的尺寸,但是它显示了JFrame整个空间的整个边界。

接下来,我认为这可能是一些数学问题,因此我决定使球比原来绘制的球更大或更小,得到相同的结果,并且在放大或缩小窗口的尺寸时遇到相同的问题。

为了获得以下输出,我需要将增量更改为9而不是最初添加的10,因为如果将其更改为10,它将变为不可见:

java - 摆动自定义绘画动画在达到帧的一半宽度后停止-LMLPHP

下面的代码产生以上输出:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.util.Random;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class ChangingColorBall {
    private JFrame frame;
    private Timer timer;
    private BallPane ballPane;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new ChangingColorBall()::createAndShowGui);
    }

    private void createAndShowGui() {
        frame = new JFrame(getClass().getSimpleName());
        ballPane = new BallPane();

        timer = new Timer(100, e -> {
            ballPane.increaseX();
        });

        ballPane.setBorder(BorderFactory.createLineBorder(Color.RED));

        frame.add(ballPane);

        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        timer.start();
    }

    @SuppressWarnings("serial")
    class BallPane extends JPanel {
        private int x;
        private static final int Y = 50;
        private static final int SIZE = 20;
        private Color color;
        private Random r;

        public void increaseX() {
            x += 9;
            r = new Random();
            color = new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255));
            revalidate();
            repaint();
        }

        public int getX() {
            return x;
        }

        public void setX(int x) {
            this.x = x;
        }

        public Color getColor() {
            return color;
        }

        public void setColor(Color color) {
            this.color = color;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;

            g2d.setColor(color);
//          g2d.fill(new Ellipse2D.Double(x, Y, SIZE, SIZE));
            g2d.fillOval(x, Y, SIZE, SIZE);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 100);
        }
    }
}


我还认为这可能与Shapes API有关,因此决定将其也更改为fillOval并获得相同的结果,我还不能发布GIF,但稍后会在必要时添加它。

我正在MacBook Pro(13英寸Retina显示屏,2015年初)上的macOS Sierra 10.12.6(16G29)下工作,并在Java 1.8下运行它

稍后,我还将在自己的PC上而不是在工作的Mac上测试此代码,这可能是与Swing API相关的错误还是我自己的代码中的错误?如果是这样,我在做什么错?既然对我来说不清楚

最佳答案

问题是您无意中覆盖了getX()类中JComponent中定义的BallPane方法。

结果,每次JPanel访问时getX()的x坐标也会发生变化,因为getX()现在返回您的字段x,该字段定义了球的运动方式并因此导致了这种行为。您应该从getX()中删除​​方法BallPane或重命名它。

09-10 07:14
查看更多