paintComponent无法正常工作

这可能是一个愚蠢的问题,但我如何调用paintComponent? 它根本不显示对象。 它在公共类Ball内扩展了JPanel实现的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完成的。

你实际遇到的问题是speedy speedxspeedy0 ,这意味着你的球永远不会移动……

另一个问题是ballAdder类正在使用FlowLayoutBall类没有提供有关它的首选大小的任何细节,这意味着Ball面板的首选大小为0x0

评论

您的设计可扩展性存在严重问题。 除了你会发现由于布局问题而难以向UI添加一个球以外的事实……

每个Ball都有它自己的线程。 这意味着,您添加的球越多,将要运行的线程越多。 这将导致资源不断流失并影响应用程序的性能。

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

第一次修复

为了解决你的第一个问题,你可以做这样的事……

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

这个修复的问题在于你只能在容器上安装一个Ball ,因为它需要占用最大的可用空间。

您可能希望阅读使用布局管理器以获取更多详细信息

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

一个(可能的)更好的解决方案是使用单个JPanel作为“球坑”,其保持对球列表的引用。

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

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

恕我直言,这更容易尝试与布局经理战斗或编写自己的…

在此处输入图像描述

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