paintComponent不起作用 [英] paintComponent not working

查看:83
本文介绍了paintComponent不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这可能是一个愚蠢的问题,但是我怎么称呼paintComponent?它根本不显示对象.在公共类Ball内,它扩展了JPanel实现Runnable.

this may be a silly question but How do i call the paintComponent? Its not displaying the object at all. its within the, public class Ball extends JPanel implements Runnable.

public class Balls {

    public static void main(String[] args) {
        new Balls();
    }

    public Balls() {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                JFrame frame = new JFrame("Balls!");
                frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
                frame.add(new ballAdder());
                frame.setSize(1000, 1000);
                frame.setVisible(true);

            }
        });
    }

    public class ballAdder extends JPanel {

        public ballAdder() {
            add(new Ball(5, 5));

        }
    }

    public class Ball extends JPanel implements Runnable {

        public int x, y;
        public int speedx, speedy;
        public int width = 40, height = 40;

        public Ball(int x, int y) {
            this.x = x;
            this.y = y;
            new Thread(this).start();

        }

        public void move() {
            x += speedx;
            y += speedy;
            if (0 > x || x > 950) {
                speedx = -speedx;
            }
            if (0 > y || y > 950) {
                speedy = -speedy;
            }
            repaint();
        }

        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.setColor(Color.BLACK);
            g.fillOval(x, y, width, height);
        }

        public void run() {
            while (true) {
                move();
                try {
                    Thread.sleep(20);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

推荐答案

您永远不要自己调用paintComponent(或paint).这是由RepaintManager完成的.

You should never call paintComponent (or paint) yourself. This is done by the RepaintManager.

您实际上遇到的问题是事实speedxspeedy0,这意味着您的球永远不会移动...

The problem you're actually having is that fact speedx and speedy or 0, meaning you balls never move...

另一个问题是ballAdder类正在使用FlowLayout,而您Ball类未提供有关其首选大小的任何详细信息,这意味着Ball面板的首选大小为0x0

The other issue is that the ballAdder class is using a FlowLayout and you Ball class is not providing any details about it's preferred size, meaning that the Ball panel has a preferred size of 0x0.

查看

设计的可伸缩性存在重大问题.除了您会发现由于布局问题而很难在UI中添加一个以上的球之外……

There is a significant issue with scalability with your design. Apart from the fact that you're going to find it difficult to add more then one ball to the UI because of layout issues...

每个Ball都有它自己的线程.这意味着,添加的球越多,将要运行的线程就越多.这将持续消耗资源并影响应用程序的性能.

Each Ball has it's own thread. This means, the more balls you add, the more threads that are going to be running. This is going to have a steady drain on resources and effect the performance of your application.

最好提供一个Drawable对象的概念,该对象知道应该在该对象的容器中显示它的位置,并且可以在paintComponent中显示为painted.通过使用单个javax.swing.Timer,它应该更有能力支持越来越多的随机球.

It would be better to provide a concept of a Drawable object which knew where it should be displayed within the concept it's container and could be painted from within the paintComponent. By utilising a single javax.swing.Timer it should be more capable of supporting a growing number of random balls.

首次修复

要解决您的第一个问题,可以执行以下操作...

To fix you're first issue, you could do something like this...

public class ballAdder extends JPanel {
    public ballAdder() {
        setLayout(new BorderLayout());
        add(new Ball(5, 5));
    }
}

此修复程序的问题在于,您将只能在容器上只有一个Ball,因为它将要占用最大的可用空间.

The problem with this fix is that you're only ever going to be able to have a single Ball on the container, as it will want to occupy the maximum available space.

您可能想通读使用布局管理器了解更多详情

You might want to have a read through Using Layout Managers for more details

一个(可能)更好的解决方案

(可能)更好的解决方案是使用单个JPanel作为球坑",该球坑保留了对球列表的引用.

A (possible) better solution would be to use a single JPanel as a "ball pit" which maintained a reference to list of balls.

然后,您将使用BallPitPanepaintComponent方法绘制所有球(在球列表中).

You would then use the BallPitPane's paintComponent method to draw all the balls (in the balls list).

通过使用单个javax.swing.Timer,您可以遍历球列表并更新那里的位置(在BallPitPane

Through the use of a single javax.swing.Timer, you could iterate through the balls list and update there positions (within the context of the BallPitPane

恕我直言,这比尝试与布局管理器抗争或编写自己的脚本更容易.

IMHO, this easier then trying to fight with the layout managers or writing your own...

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Bounce {

    public static void main(String[] args) {
        new Bounce();
    }

    public Bounce() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new BallPitPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class BallPitPane extends JPanel {

        private List<Ball> balls;
        private Random rand;

        public BallPitPane() {
            rand = new Random(System.currentTimeMillis());
            balls = new ArrayList<>(25);
            Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (balls.isEmpty()) {
                        balls.add(new Ball(BallPitPane.this));
                    }

                    if (rand.nextBoolean()) {
                        balls.add(new Ball(BallPitPane.this));
                    }

                    for (Ball ball : balls) {
                        ball.move();
                    }
                    repaint();
                }
            });
            timer.start();
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            for (Ball ball : balls) {
                ball.paint(g2d);
            }
            g2d.dispose();
        }
    }

    protected static int random(int min, int max) {

        return (int)Math.round(Math.random() * (max - min)) + min;

    }

    public static class Ball {

        public static final int WIDTH = 10;
        public static final int HEIGHT = 10;

        private int x;
        private int y;

        private int deltaX;
        private int deltaY;

        private Color color;
        private BallPitPane parent;

        public Ball(BallPitPane parent) {
            this.parent = parent;
            x = parent.getWidth() / 2;
            y = parent.getHeight() / 2;

            deltaX = random(-4, 4);
            deltaY = random(-4, 4);

            color = new Color(random(0, 255), random(0, 255), random(0, 255));
        }

        public void move() {
            x += deltaX;
            y += deltaY;

            if (x + WIDTH > parent.getWidth()) {
                x = parent.getWidth() - WIDTH;
                deltaX *= -1;
            } else if (x < 0) {
                x = 0;
                deltaX *= -1;
            }
            if (y + HEIGHT > parent.getHeight()) {
                y = parent.getHeight() - HEIGHT;
                deltaY *= -1;
            } else if (y < 0) {
                y = 0;
                deltaY *= -1;
            }
        }

        public Color getColor() {
            return color;
        }

        public void paint(Graphics2D g2d) {

            g2d.setColor(getColor());
            g2d.fillOval(x, y, WIDTH, HEIGHT);
            g2d.setColor(Color.BLACK);
            g2d.drawOval(x, y, WIDTH, HEIGHT);

        }        
    }    
}

这篇关于paintComponent不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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