Swing 自定义绘画动画在达到帧的一半宽度后停止 [英] Swing custom painting animation stops after reaching half width of frame

查看:22
本文介绍了Swing 自定义绘画动画在达到帧的一半宽度后停止的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图回答一个与

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

import java.awt.Color;导入 java.awt.Dimension;导入 java.awt.Graphics;导入 java.awt.Graphics2D;导入 java.awt.geom.Ellipse2D;导入 java.util.Random;导入 javax.swing.BorderFactory;导入 javax.swing.JFrame;导入 javax.swing.JPanel;导入 javax.swing.SwingUtilities;导入 javax.swing.Timer;公共类ChangingColorBall {私人 JFrame 框架;私人定时器定时器;私人 BallPane ballPane;公共静态无效主(字符串 [] args){SwingUtilities.invokeLater(新的ChangingColorBall()::createAndShowGui);}私有无效 createAndShowGui() {frame = new JFrame(getClass().getSimpleName());ballPane = new BallPane();定时器 = 新定时器(100,e -> {ballPane.increaseX();});ballPane.setBorder(BorderFactory.createLineBorder(Color.RED));frame.add(ballPane);框架.pack();frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);定时器开始();}@SuppressWarnings("串行")类 BallPane 扩展 JPanel {私有整数 x;私有静态最终 int Y = 50;私有静态最终 int SIZE = 20;私人颜色颜色;私人随机r;公共无效增加X(){x += 9;r = 新随机();color = new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255));重新验证();重绘();}公共 int getX() {返回 x;}公共无效 setX(int x) {this.x = x;}公共颜色 getColor() {返回颜色;}公共无效setColor(颜色颜色){this.color = 颜色;}@覆盖受保护的无效paintComponent(图形g){super.paintComponent(g);Graphics2D g2d = (Graphics2D) g;g2d.setColor(颜色);//g2d.fill(new Ellipse2D.Double(x, Y, SIZE, SIZE));g2d.fillOval(x, Y, SIZE, SIZE);}@覆盖公共维度 getPreferredSize() {返回新维度(200, 100);}}}

我也认为它可能与 Shapes API 相关,并决定将其更改为 fillOval 以及相同的结果,我无法发布GIF 还没有,但如有必要,稍后会添加.

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

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

解决方案

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

因此,每当 getX() 访问时,JPanel 的 x 坐标也会发生变化,因为 getX() 现在返回您的field x 定义了球的移动方式,从而导致了这种行为.您应该从 BallPane 中删除方法 getX() 或重命名它.

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

解决方案

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.

这篇关于Swing 自定义绘画动画在达到帧的一半宽度后停止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆