【问题标题】:Custom JComponent Not Being Added to JPanel自定义 JComponent 未添加到 JPanel
【发布时间】:2014-03-12 20:05:25
【问题描述】:

我对我认为很简单的问题有点坚持。

我有一个自定义的 JComponent Ball,它只不过是一个简单的椭圆形。我正在尝试将球添加到已设置为 JFrame 的默认内容窗格的 JPanel(通过 frame.setContentPane(mainPanel))。除了球,我还有另外两个 Paddle 类的组件,这是我创建的另一个自定义 JComponent。奇怪的是,桨可以添加就好了。

有问题的面板故意使用绝对布局来定位元素,因为这应该是 Pong 游戏的简单再现。

在将球和两个桨添加到 JPanel 后,我运行了一个简单的测试,发现返回的组件数组只列出了两个:桨。添加所有这些并初始化JPanel和JFrame的完整代码如下:

public Pong()
{
    frame = new JFrame("Pong");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    mainPanel = new JPanel(null);

    mainPanel.setBackground(Color.black);
    mainPanel.setPreferredSize(new Dimension(500, 500));

    player = new Paddle(20, 100);
    enemy = new Paddle(20, 100);
    ball = new Ball(5, Color.GREEN);

    mainPanel.add(player);
    mainPanel.add(enemy);
    mainPanel.add(ball);
    enemy.setColor(Color.RED);

    frame.setContentPane(mainPanel);
    frame.pack();

    Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
    int x = screen.width/2 - frame.getWidth()/2;
    int y = screen.height/2 - frame.getHeight()/2;
    frame.setLocation(x, y);

    mainPanel.addKeyListener(mc);

    frame.setVisible(true);

    mainPanel.repaint();

    x = mainPanel.getWidth()/2 - ball.getWidth()/2;
    y = mainPanel.getHeight()/2 - ball.getHeight()/2;
    System.out.println("X: " + x + ", Y: " + y);
    ball.setLocation(x, y);

    x = 0;
    y = mainPanel.getHeight()/2 - player.getHeight()/2;
    System.out.println("X: " + x + ", Y: " + y);
    player.setLocation(x, y);

    x = mainPanel.getWidth() - enemy.getWidth();
    y = mainPanel.getHeight()/2 - enemy.getHeight()/2;
    System.out.println("X: " + x + ", Y: " + y);
    enemy.setLocation(x, y);

    System.out.println(Arrays.deepToString(mainPanel.getComponents()));

    mainPanel.repaint();

    frame.addMouseListener(new MouseAdapter()
    {
        @Override
        public void mousePressed(MouseEvent e)
        {
            mainPanel.requestFocus();
        }
    });

    dm.start();
    mainPanel.requestFocus();
}

球的代码如下[注意:球是私有的,因为它是类Pong的内部类,不扩展任何东西]:

private class Ball extends JComponent
{
    private int radius;
    private Color color;

    public Ball(int size, Color c)
    {
        if(size > 0)
            radius = size;
        else
            radius = 1;
        this.setPreferredSize(new Dimension(radius, radius));
        color = c;
    }

    public Ball(int size)
    {
        this(size, Color.RED);
    }

    //Getters and Setters...

    @Override
    public void paintComponent(Graphics g)
    {
        System.out.println("Radius: " + radius);
        g.setColor(color);
        g.fillOval(0, 0, radius, radius);
    }
}

这不是我在处理项目时第一次遇到这个问题,而且当我使用自定义 JComponents 以及 JPanel 上的绝对定位时,它似乎总是会发生,尽管在其他项目中,我不这样做这似乎没有问题。这可能是我忽略的非常简单的事情,但我想不出它是什么,为了我的生活。对此的任何答案将不胜感激。

如果绝对必要,all the lines of code for this project can be found here(总共超过 300 行)。

提前感谢您的帮助!

【问题讨论】:

  • 我忘了说:mc 和 dc 分别是 MoveManager 和 DisplayManager,但应该与球的显示无关。只是为了清除那些未知的变量。
  • 您忘记在Ball.paintComponent() 内拨打super.paintComponent(g)
  • 不过,我也没有为桨这样做。我会解决这个问题,但这似乎不是问题的原因。

标签: java swing jcomponent


【解决方案1】:

当您使用空布局将组件添加到面板时,您需要负责设置组件的sizelocation

如果你不设置大小,那么它将是零,所以没有东西可以画。

【讨论】:

  • +1。 OP 应在 Ball 类构造函数中将 setPreferredSize 替换为 setSize。在OP's code 稍作检查,他/她已经覆盖(可能是在不知不觉中)getHeightgetWidth 类中的 Paddle 方法,这就是为什么这个被绘制但 Ball 不是。
【解决方案2】:

解决方案很简单。

在 Ball 类中添加以下调用构造函数和 setRadius 方法:

this.setSize(new Dimension(radius, radius));

一切都会好起来的。基本上,首选大小不是强制的,所以要明确:设置大小。否则,当重新绘制 JPanel 时,该组件的大小为 0 并被跳过。

(根据评论编辑,谢谢,我的 Swing 生锈了)

【讨论】:

  • 不要覆盖这些方法。您应该使用 setSize(...) 或 setBounds(...) 方法。
  • 谢谢,已编辑。我的 Swing 生锈了,忘了这是最佳做法。
猜你喜欢
  • 1970-01-01
  • 2020-09-11
  • 1970-01-01
  • 2015-02-04
  • 1970-01-01
  • 2022-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多