[英]Java Swing Add JPanel to JPanel
I am currently trying to build a 2D game with Java's Swing.我目前正在尝试使用 Java 的 Swing 构建 2D 游戏。 For this, I have my main class
Puzzle
which is subclassing JFrame
.为此,我有我的主类
Puzzle
,它是JFrame
子类。 To my frame I add my main JPanel
which consists of several JPanel
s added together (each of them being a new piece).我的帧添加我主要
JPanel
它由几个JPanel
叠加在一起(它们中的每一个被新件)。
EDIT 2: PlayingField
is my model which will store the current location of each piece.编辑 2:
PlayingField
是我的模型,它将存储每件作品的当前位置。 One can select a piece with the mouse (the plan is to highlight it) and move it with the arrow keys as long as the next step (a full cell, so approx. 100 pixel) isn't the location of one of the other pieces.可以用鼠标选择一块(计划是突出显示它)并用箭头键移动它,只要下一步(一个完整的单元格,所以大约 100 像素)不是另一个的位置件。 As of right now,
PlayingField
does not store any data since the pieces are missing.截至目前,
PlayingField
不存储任何数据,因为这些片段丢失了。
private void createAndShowGui() {
// The playing-field with a 4x6 grid.
PlayingField field = new PlayingField(4, 6);
JPanel mainPanel = new ComputerView(field);
setTitle("Puzzle");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 600);
add(mainPanel);
setVisible(true);
}
The method above will create my frame and adds the main panel.上面的方法将创建我的框架并添加主面板。 The following method is my main panel which adds several
JPanel
s to itself.以下方法是我的主面板,它向自身添加了几个
JPanel
。
public ComputerView(PlayingField field) {
this.field = field;
this.setLayout(null);
JPanel topLeft = new GamingPiece(PlayingField.TOP_LEFT);
add(topLeft);
JPanel topRight = new GamingPiece(PlayingField.TOP_RIGHT);
add(topRight);
JPanel bottomLeft = new GamingPiece(PlayingField.BOTTOM_LEFT);
add(bottomLeft);
}
Each GamingPiece
or rather my sub- JPanel
s are drawing a basic piece (I only drawing one and rotating the others, since all consists of the same arbitrary shape).每个
GamingPiece
或者更确切地说我的子JPanel
正在绘制一个基本块(我只绘制一个并旋转其他的,因为它们都由相同的任意形状组成)。 The GamingPiece
class also subclasses JPanel
and invokes the JPanel#paintComponent()
method to draw the piece. GamingPiece
类还GamingPiece
JPanel
并调用JPanel#paintComponent()
方法来绘制块。
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.YELLOW);
g2.fillPolygon(pieceX, pieceY, pieceX.length);
}
Since I am pretty new to Java I really do not know how to do it properly.由于我对 Java 还很陌生,我真的不知道如何正确地做到这一点。 If I add my pieces by creating a new object and adding it to the main panel, it won't show all of them, only the last one added.
如果我通过创建一个新对象并将其添加到主面板来添加我的作品,它不会显示所有作品,只会显示最后一个。 Some don't even seem to work, even if they're the only ones added (to explain my situation: I have for pieces which are the same arbitrary shape just rotated differently but using
Graphics2D#rotate()
doesn't seem to work fine).有些甚至似乎不起作用,即使它们是唯一添加的(解释我的情况:我有相同的任意形状的碎片只是旋转不同,但使用
Graphics2D#rotate()
似乎不起作用美好的)。
I hope I explained my situation and my problem well enough fo you guys to help me.我希望我能很好地解释我的情况和我的问题,以便你们帮助我。 Thanks in advance!
提前致谢!
EDIT:编辑:
Puzzle.java拼图.java
package programming.schimmler;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import programming.schimmler.model.PlayingField;
import programming.schimmler.view.ComputerView;
public class Puzzle extends JFrame {
...
Invoking the createAndShowGui()
...
private void createAndShowGui() {
// The playing-field with a 4x6 grid.
PlayingField field = new PlayingField(4, 6);
JPanel mainPanel = new ComputerView(field);
setTitle("Puzzle");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 600);
add(mainPanel);
setVisible(true);
}
}
ComputerView.java计算机视图.java
package programming.schimmler.view;
import java.util.HashSet;
import java.util.Set;
import javax.swing.JPanel;
import programming.schimmler.model.PlayingField;
public class ComputerView extends JPanel {
...
Instance variables
....
public ComputerView(PlayingField field) {
this.field = field;
this.setLayout(null);
JPanel topLeft = new GamingPiece(PlayingField.TOP_LEFT);
add(topLeft);
JPanel topRight = new GamingPiece(PlayingField.TOP_RIGHT);
add(topRight);
JPanel bottomLeft = new GamingPiece(PlayingField.BOTTOM_LEFT);
add(bottomLeft);
}
}
GamingPiece.java GamingPiece.java
package programming.schimmler.view;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JPanel;
import programming.schimmler.model.PlayingField;
/**
*
*/
public class GamingPiece extends JPanel {
...
public GamingPiece(int type) {
switch (type) {
// Need to draw each polygon from different coordinates since rotating did not work yet.
case PlayingField.TOP_LEFT:
pieceX = new int[] { 100, 100, 300, 300, 200, 200, 100 };
pieceY = new int[] { 100, 100, 100, 200, 200, 300, 300 };
break;
case PlayingField.TOP_RIGHT:
pieceX = new int[] { 400, 400, 300, 300, 200, 200 };
pieceY = new int[] { 0, 200, 200, 100, 100, 0 };
break;
case PlayingField.BOTTOM_LEFT:
pieceX = new int[] { 0, 200, 200, 100, 100, 0 };
pieceY = new int[] { 400, 400, 300, 300, 200, 200 };
break;
case PlayingField.BOTTOM_RIGHT:
pieceX = new int[] { 400, 400, 300, 300, 200, 200 };
pieceY = new int[] { 400, 200, 200, 300, 300, 400 };
break;
case PlayingField.SQUARE:
pieceX = new int[] { 100, 300, 300, 100 };
pieceY = new int[] { 100, 100, 300, 300 };
break;
}
setLayout(null);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.YELLOW);
g2.fillPolygon(pieceX, pieceY, pieceX.length);
}
}
These classes above are the only classes interacting with my GUI, no other classes take part.上面的这些类是唯一与我的 GUI 交互的类,没有其他类参与。
You are overcomplicating things by trying to add JPanel
puzzle pieces to your JPanel
puzzle board.通过尝试将
JPanel
拼图添加到您的JPanel
拼图板,您使事情变得过于复杂。 Problems will rapidly become apparent with your non-rectangular puzzle pieces, like the TOP_LEFT
shape, which has a cut-out from the lower right side of the piece.对于非矩形拼图,问题会很快变得明显,例如
TOP_LEFT
形状,它从拼图的右下方切开。 When it comes time to overlap the puzzle pieces, to fit the cut-away portions together, the piece added later will occlude pieces drawn earlier.当需要重叠拼图块时,将切掉的部分组合在一起,稍后添加的块将遮挡之前绘制的块。
For instance, if you try to nest a TOP_LEFT piece (A) and a BOTTOM_RIGHT piece (B) together.例如,如果您尝试将 TOP_LEFT 部分 (A) 和 BOTTOM_RIGHT 部分 (B) 嵌套在一起。
AAAAAA BBB
AAAAAA BBB
AAA BBBBBB
AAA BBBBBB
You will only see:你只会看到:
+---+------+
|AAA| BBB|
|AAA| BBB|
|AAA|BBBBBB|
|AAA|BBBBBB|
+---+------+
The overlapping area will be drawn by only one of the panels.重叠区域将仅由其中一个面板绘制。 The entire area of the B piece, including the blank space, will be drawn in the area of the second piece, on top of whatever the A piece hoped to display.
B 块的整个区域,包括空白区域,将被绘制在第二块的区域中,在 A 块希望显示的任何内容之上。
You might be able to get around this by setting the JPanel
to be transparent, and not calling super.paintComponent()
which paints the entire component the background colour.您可以通过将
JPanel
设置为透明来解决此问题,而不是调用super.paintComponent()
将整个组件绘制为背景颜色。 But then you still have to draw the shape on the JPanel
, and position the JPanel
properly on the parent JPanel
.但是您仍然需要在
JPanel
上绘制形状,并将JPanel
正确放置在父JPanel
。
Forget panels within panels!忘记面板中的面板! Just draw the pieces on the parent
JPanel
.只需在父
JPanel
上绘制碎片即可。
Example:例子:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Puzzle {
public static void main(String[] args) {
SwingUtilities.invokeLater(Puzzle::new);
}
private final static int shape_x[] = { -100, 100, 100, 0, 0, -100 };
private final static int shape_y[] = { -100, -100, 0, 0, 100, 100 };
public Puzzle() {
JFrame frame = new JFrame("Puzzle");
frame.setSize(600, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
View view = new View();
frame.setContentPane(view);
Shape l_shape = new Polygon(shape_x, shape_y, shape_x.length);
view.pieces.add(new Piece(Color.YELLOW, l_shape, 0, 100, 100));
view.pieces.add(new Piece(Color.GREEN, l_shape, 180, 300, 300));
view.pieces.add(new Piece(Color.RED, l_shape, 65, 450, 145));
frame.setVisible(true);
}
}
@SuppressWarnings("serial")
class View extends JPanel {
final List<Piece> pieces = new ArrayList<>();
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D gc = (Graphics2D) g;
for (Piece piece : pieces)
piece.draw(gc);
}
}
class Piece {
final Color color;
final Shape shape;
final int angle;
int x, y; // Move pieces by by changing these
Piece(Color color, Shape shape, int angle, int x, int y) {
this.color = color;
this.shape = shape;
this.angle = angle;
this.x = x;
this.y = y;
}
void draw(Graphics2D gc) {
AffineTransform tf = gc.getTransform();
gc.translate(x, y);
gc.rotate(Math.toRadians(angle));
gc.setColor(color);
gc.fill(shape);
gc.setTransform(tf);
}
}
Note that this is also a Minimal, Complete and Verifiable example.请注意,这也是一个最小、完整和可验证的示例。 Minimal: No
package
statement;最小:无
package
声明; No extra HashSet
and Set
imports which aren't used;没有未使用的额外
HashSet
和Set
导入; doesn't try to do anything except show 3 game pieces.除了展示 3 个游戏片段外,不会尝试做任何事情。 It is complete: a single file you can compile, and run.
它是完整的:您可以编译和运行单个文件。 It is verifiable: you can run it and see it shows 3 game pieces.
它是可验证的:您可以运行它并看到它显示 3 个游戏块。
As a bonus, it shows Graphics2D.rotate()
working, with one piece rotated 180°, and another rotated at an angle that is not appropriate for your puzzle but useful in demonstrating the that rotate works just fine.作为奖励,它显示
Graphics2D.rotate()
工作,其中一块旋转了 180°,另一块旋转的角度不适合您的拼图,但有助于证明旋转工作正常。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.