繁体   English   中英

向Java Swing中的JPanel添加更多组件后,Repaint()无法正常工作

[英]Repaint() does not work after adding more components to JPanel in Swing, Java

我从Java开始,想要制作一个简单的Pong游戏,以了解在Java中显示内容的方式。 我创建了两个类,它们都扩展了JPanel并每隔16.6毫秒调用一次repaint()函数。 我将两者都添加到我添加到框架的JPanel中,但是仅显示我首先添加的组件。

我尝试在两个类中的repaint() revalidate()之后repaint() revalidate() ,并确保Timer实际起作用,并且实际上调用了它的actionPerformed()方法。

这是主要方法:

public class Main {
  public static void main(String[] args){
    JFrame frame = new JFrame("Pong");
    //...
    JPanel mainPanel = new JPanel();

    mainPanel.add(new Player());
    mainPanel.add(new Ball(frameWidth/2, frameHeight/2 -40));

    frame.add(mainPanel);
  }
}

这是这些类的重要代码(这两个类基本上是相同的):

public class Player extends JPanel {

  public Player(){
    setPreferredSize(new Dimension(Main.frameWidth, Main.frameHeight));
    setBackground(Color.BLACK);

    new Timer(1000/60, new ActionListener(){
      public void actionPerformed(ActionEvent e){
        update();
        repaint();
      }
    }).start();
  }
//...
  public void paintComponent(Graphics g){
    super.paintComponent(g);

    g.setColor(Color.WHITE);
    g.fillRect(x, y, width, height);
  }
}

(当然,我省略了诸如@Override或unseccaryary之类的东西来缩短代码)

该代码仅绘制Player,尽管我希望它显示mainPanel所有组件。

这是您可以(希望)运行的示例。 我不得不将其拆分为3个文件,因为我喜欢匿名类:

Main.java

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Main {

  public static void main(String[] args){
    JFrame frame = new JFrame("Pong");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(800, 800);

    JPanel mainPanel = new JPanel();

    mainPanel.add(new Player());
    mainPanel.add(new Ball());

    frame.add(mainPanel);

    frame.setVisible(true);
  }
}
///////
Player.java
//////
import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class Player extends JPanel{
  private int x = 20, y = 300, width = 20, height = 100;
  public Player(){
    setPreferredSize(new Dimension(800, 800));
    setBackground(Color.BLACK);

    new Timer(1000/60, new ActionListener(){
      @Override
      public void actionPerformed(ActionEvent e){
        repaint();
      }
    }).start();
  }


  @Override
  public void paintComponent(Graphics g){
    super.paintComponent(g);

    g.setColor(Color.WHITE);
    g.fillRect(x, y, width, height);
  }
}
//////
Ball.java
//////
import javax.swing.JPanel;
import javax.swing.Timer;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class Ball extends JPanel{
  private int x = 20, y = 300, width = 20, height = 100;
  public Ball(){
    setPreferredSize(new Dimension(800, 800));
    setBackground(Color.BLACK);
    new Timer(1000/60, new ActionListener(){
      @Override
      public void actionPerformed(ActionEvent e){
        repaint();
      }
    }).start();
  }

  @Override
  public void paintComponent(Graphics g){
    super.paintComponent(g);

    g.setColor(Color.WHITE);
    g.fillRect(x, y, width, height);
  }
}

Player类的paintComponent()方法中,每次都绘制完全相同的Rectangle 为了获得动画效果,每次绘制矩形时,都需要更改其大小或位置,或同时更改二者。 您期望Player做什么? 它是否应该沿着窗口的左边缘上下移动? 您是否看过Oracle Java教程中名为“ 如何使用Swing计时器 ”的课程

编辑

现在我看到Player隐藏了Ball ,这是因为JPanel的默认布局管理器。 以下代码本质上是您发布的代码,但是我将GridLayout设置为mainPanel的布局管理器。 同样,一个Java源代码文件可能包含多个类,但恰好一个类必须是public 因此,在下面的代码中,仅Main类是public

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Main {

    public static void main(String[] args) {
        JFrame frame = new JFrame("Pong");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel mainPanel = new JPanel(new GridLayout(0, 2));
        mainPanel.add(new Player());
        mainPanel.add(new Ball());
        frame.add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
}

class Player extends JPanel {

    public Player() {
        setBorder(BorderFactory.createLineBorder(Color.RED, 2, false));
        setPreferredSize(new Dimension(800, 800));
        setBackground(Color.BLACK);

        new Timer(1000 / 60, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                repaint();
            }
        }).start();
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.setColor(Color.WHITE);
        g.fillRect(20, 100, 20, 100);
    }
}

class Ball extends JPanel {

    public Ball() {
        setBorder(BorderFactory.createLineBorder(Color.CYAN, 2, false));
        setPreferredSize(new Dimension(800, 800));
        setBackground(Color.BLACK);
        new Timer(1000 / 60, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                repaint();
            }
        }).start();
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.setColor(Color.WHITE);
        g.fillRect(300, 300, 10, 10);
    }
}

这是GUI的屏幕截图...

主要

我只是意识到,如果我手动扩展窗口,第二个JPanel会显示在负责Player的一个下面! 这意味着我需要以某种方式设置面板的位置,对吗?

@阿布拉

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM