达到框架的一半宽度后,Swing 自定义绘画动画停止

Swing custom painting animation stops after reaching half width of frame

我试图回答一个与 moving a ball across the screen while changing its color over time, however I came through a weird bug, (most probably in my code) and while asking this question I came to a related question 相关的问题,但该问题使用的是 Client-Server 架构,而我的只是一个 Swing 应用 运行 本身。

发生的事情是当圆圈/球,无论你想如何命名,到达 JPanelJFrame 的一半宽度时,它就会变得不可见或停止。

一开始我以为可能是我的JPanel定位不好,后来加了一个Border,这样我就可以看到它的尺寸了,但是它显示的是整个边框space 的 JFrame.

接下来我觉得可能是一些算术题,所以我决定把这个球比我原来画的大和小,得到相同的结果,放大或缩小时也有同样的问题window 的尺码。

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

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

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 以及相同的结果,我不能 post 还没有 GIF,但如有必要,稍后会添加它。

我在 MacBook Pro(13'' Retina 显示屏,2015 年初)上使用 macOS Sierra 10.12.6 (16G29) 进行编译,运行 它在 Java 1.8

稍后我也会在我自己的 PC 上测试此代码,而不是我工作的 Mac,但是,这可能是与 Swing API 相关的错误还是我自己代码中的错误?如果是这样,我做错了什么?因为我好像不太清楚

问题是您在 BallPane class.

中无意中覆盖了 JComponent 中定义的 getX() 方法

因此,每当 getX() 访问时 JPanel 的 x 坐标也发生变化,现在 getX() returns 您的字段 x正在定义球如何移动,从而导致这种行为。您应该从 BallPane 中删除方法 getX() 或重命名它。