我从Java开始,想做一个简单的Pong游戏,以了解在Java中显示内容的方式。我创建了两个类,它们均扩展了JPanel并每隔16.6毫秒调用一次repaint()
函数。我将两者都添加到添加到框架的JPanel中,但仅显示我首先添加的组件。
在两个类的revalidate()
之后,我都尝试过repaint()
,并确保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);
}
}
答案 0 :(得分:1)
在类paintComponent()
的方法Player
中,您每次都绘制完全相同的Rectangle
。为了获得动画效果,每次绘制矩形时,都需要更改其大小或位置,或同时更改二者。您期望Player
做什么?它是否应该沿着窗口的左边缘上下移动?您是否看过名为How to Use Swing Timers的课程,该课程是 Oracle 的 Java教程的一部分?
编辑
我现在看到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的屏幕截图...
答案 1 :(得分:0)
我刚刚意识到,如果手动扩展窗口,第二个JPanel会显示在负责Player的一个下面!这意味着我需要以某种方式设置面板的位置,对吗?
@Abra