我有两个JPanel。一个面板有一个以0,0绘制的100x100矩形。另一个有一个100x100的矩形,绘制在100,100。我的问题是,当两个JPanel都绘制在JFrame的内容窗格上时,一个JPanel(最后绘制的一个)覆盖另一个,隐藏其图形。下面是过度简化的代码,绘制了两个矩形和我尝试过的东西。
package playground;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Playground{
public Playground(){
JFrame frame = new JFrame("My Frame");
frame.setSize(400, 400);
JPanel backPanel = new JPanel(){;
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
Rectangle2D rect = new Rectangle2D.Double(0, 0, 100, 100);
g2.draw(rect);
}
};
JPanel frontPanel = new JPanel(){
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
Rectangle2D rect = new Rectangle2D.Double(150, 150, 100, 100);
g2.draw(rect);
}
};
frontPanel.setOpaque(true); //Does nothing
frontPanel.setBackground(new Color(0, 0, 0, 0)); //Does nothing
frontPanel.setForeground(new Color(0, 0, 0, 0)); //Erases the rectangle drawn
frame.getContentPane().add(backPanel);
frame.getContentPane().add(frontPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args){
System.out.println("Hello World");
new Playground();
}
}
如果有人关心我为什么要这样做,
我正在创造游戏突破。我是一名新手程序员,我不了解游戏理论。所以我决定避免大量渲染和缓冲的最聪明的方法就是拥有四个JPanel。背面有静态JPanel,上面画有图像(有趣的背景图片)。一个带有划桨的JPanel。一个带有砖块的JPanel。还有一个带有球的JPanel。我的理由是,如果它没有被移动,背景和砖块没有被击中,我将不必重绘它。如果一个砖让我说是命中,我将更新砖块的arrayList并在相应的JPanel上调用重绘。
答案 0 :(得分:4)
我是一名新手程序员,我对游戏理论一无所知。
好的,我们可以解决这个问题。
所以我决定避免大量渲染和缓冲的最聪明的方法是拥有四个JPanel。
你只是不必要地复杂了你的程序。
将JPanel视为画布。你想绘制整个Breakout游戏;一块JPanel帆布上的砖块,球拍和球。不用担心,如果你愿意的话,你将能够足够快地重绘整个画布,以获得每秒60帧。
这样做的方法是创建一个Brick类,一个Paddle类和一个Ball类。您创建一个Game Model类,其中包含Paddle类的一个实例,Ball类的一个实例和Brick类的实例列表。
Brick类将有字段来确定它在墙上的位置,当球与砖碰撞时得分的点数,砖的颜色以及知道如何绘制一块砖的绘制方法。
球类将有字段来确定其x,y位置,方向,速度以及知道如何绘制球的绘制方法。
Paddle类将有字段来确定它的x,y位置,方向,速度,以及知道用于绘制划桨的绘制方法。
Game Model类将有方法确定球何时与砖碰撞,确定球何时与砖碰撞,确定球何时与墙碰撞,以及调用其他模型类绘制方法的draw方法画一个球,一个球拍和一堵砖墙。
这应该足以让你开始朝着正确的方向前进。
编辑回答问题:
我如何在所有这些类中实现draw方法?
这是Ball类的示例。我没有测试moveBall方法,所以可能需要一些调整
import java.awt.Graphics;
import java.awt.geom.Point2D;
public class Ball {
private Point2D position;
/** velocity in pixels per second */
private double velocity;
/**
* direction in radians
* <ul>
* <li>0 - Heading east (+x)</li>
* <li>PI / 2 - Heading north (-y)</li>
* <li>PI - Heading west (-x)</li>
* <li>PI * 3 / 2 - Heading south (+y)</li>
* </ul>
* */
private double direction;
public Point2D getPosition() {
return position;
}
public void setPosition(Point2D position) {
this.position = position;
}
public double getVelocity() {
return velocity;
}
public void setVelocity(double velocity) {
this.velocity = velocity;
}
public double getDirection() {
return direction;
}
public void setDirection(double direction) {
this.direction = direction;
}
public void moveBall(long milliseconds) {
Point2D oldPosition = position;
// Calculate distance of ball motion
double distance = velocity / (1000.0D * milliseconds);
// Calculate new position
double newX = distance * Math.cos(direction);
double newY = distance * Math.sin(direction);
newX = oldPosition.getX() + newX;
newY = oldPosition.getY() - newY;
// Update position
position.setLocation(newX, newY);
}
public void draw(Graphics g) {
int radius = 3;
int x = (int) Math.round(position.getX());
int y = (int) Math.round(position.getY());
// Draw circle of radius and center point x, y
g.drawOval(x - radius, y - radius, radius + radius, radius + radius);
}
}
绘制方法将球拉到实际所在的任何位置。这就是所有的绘制方法。
实际上移动球是Game Model类的责任。移动球的方法包含在本课程中,因为移动球所需的信息存储在Ball类中。
我给球的半径为3,或直径为6像素。您可能希望将球变大,并使用fillOval方法而不是drawOval。
我应该以30毫秒的间隔调用repaint()
基本上,是的。
在psudeocode中,您创建一个游戏循环
while (running) {
update game model();
draw game();
wait;
}
首先,您更新游戏模型。我给了你一个Ball课程。你会有类似的桨和砖类。他们都有绘画方法。
您的游戏模型类以正确的顺序调用所有这些绘制方法。在Breakout中,你首先绘制边界,然后是砖块,然后是桨,最后是球。
你的JPanel(canvas)在Game Model类中调用一个draw方法。
我没有示例游戏向您展示,但如果您阅读文章Sudoku Solver Swing GUI,您将看到如何组合Swing GUI,您将看到模型类如何实现绘制方法。
我建议您停止使用Breakout一段时间并完成Oracle Swing Tutorial。不要急于跳过任何部分来编写程序。完成整个教程,以便在尝试使用之前了解Swing的工作原理。