Swing custom painting animation stops after reaching half width of frame

我只是一个虾纸丫 提交于 2019-12-04 05:51:30

问题


I was trying to answer a question related to 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 but that question is using a Client-Server architecture while mine is simply a Swing app running itself.

What is happening is that when the circle / ball, however you want to name it, reaches the half width of the JPanel or JFrame it becomes invisible or stops.

At first I thought it could be my JPanel being badly positioned, but I added a Border to it, so I could see its dimensions, but it's showing the whole border around the whole space of the JFrame.

Next I thought it could be some arithmetical problem, so I decided to make the ball larger and smaller than what I was originally painting it, giving me the same result, and having the same issue when I enlarge or reduce the window's size.

To get the following output I needed to change the increment by 9 instead of 10 that I was adding originally, because if I change it to 10 it becomes invisible:

The below code produces the above output:

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);
        }
    }
}

I also thought it could be something related to the Shapes API, and decided to change it to fillOval as well with the same results, I can't post a GIF yet, but will add it later if necessary.

I'm working under macOS Sierra 10.12.6 (16G29) on a MacBook Pro (13'' Retina display, early 2015) compiling and running it under Java 1.8

I'll test this code later as well on my own PC and not my work's Mac, however, could this be a bug related to Swing's API or a bug in my own code? If so, what am I doing wrong? Since it doesn't seem clear to me


回答1:


The issue is that you are inadvertently overriding the getX() method defined in JComponent in your BallPane class.

As a result the x coordinate of the the JPanel whenever accessed by getX() is also changing as getX() now returns your field x which is defining how the ball moves and thus resulting in this behavior. You should either remove the method getX() from BallPane or rename it.



来源:https://stackoverflow.com/questions/46779919/swing-custom-painting-animation-stops-after-reaching-half-width-of-frame

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!