Java Swing将JPanel添加到JPanel [英] Java Swing Add JPanel to JPanel

查看:149
本文介绍了Java Swing将JPanel添加到JPanel的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在尝试使用Java的Swing构建2D游戏.为此,我有主类Puzzle,它是子类JFrame的子类.在我的框架中添加主要的JPanel,它由几个添加在一起的JPanel组成(每个都是新的).

I am currently trying to build a 2D game with Java's Swing. For this, I have my main class Puzzle which is subclassing JFrame. To my frame I add my main JPanel which consists of several JPanels added together (each of them being a new piece).

PlayingField是我的模型,它将存储每块的当前位置. 只要下一步(一个完整的单元格,大约100个像素)不是另一个的位置,就可以用鼠标选择一块(计划将其突出显示)并用方向键移动它.件.截至目前,由于缺少片段,PlayingField不会存储任何数据.

EDIT 2: PlayingField is my model which will store the current location of each piece. 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. As of right now, PlayingFielddoes not store any data since the pieces are missing.

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);
}

以上方法将创建我的框架并添加主面板.以下方法是我的主面板,它在自身中添加了几个JPanel.

The method above will create my frame and adds the main panel. The following method is my main panel which adds several JPanels to itself.

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或更确切地说是我的sub- JPanel都在绘制一个基本零件(我只绘制一个零件,然后旋转其他零件,因为所有零件都由相同的任意形状组成). GamingPiece类也是JPanel的子类,并调用JPanel#paintComponent()方法绘制图块.

Each GamingPiece or rather my sub-JPanels are drawing a basic piece (I only drawing one and rotating the others, since all consists of the same arbitrary shape). The GamingPiece class also subclasses JPanel and invokes the JPanel#paintComponent() method to draw the piece.

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;

    g2.setColor(Color.YELLOW);
    g2.fillPolygon(pieceX, pieceY, pieceX.length);
}

问题和我的问题

由于我是Java的新手,所以我真的不知道如何正确地做它.如果我通过创建一个新对象并将其添加到主面板中来添加作品,它将不会显示所有作品,而只会显示最后一个作品.即使是添加的唯一零件,有些零件似乎也不起作用(以解释我的情况:对于相同形状的零件,我只是旋转不同而使用Graphics2D#rotate()似乎效果不佳)

The Problem And My Questions

Since I am pretty new to Java I really do not know how to do it properly. 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).

我希望我向大家解释了我的情况和问题,足以帮助我.预先感谢!

I hope I explained my situation and my problem well enough fo you guys to help me. Thanks in advance!

Puzzle.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

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

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);
    }
}

以上这些类是与我的GUI交互的 only 类,没有其他类参与.

These classes above are the only classes interacting with my GUI, no other classes take part.

推荐答案

您正在尝试通过将JPanel拼图块添加到您的JPanel拼图板上来使事情变得过于复杂.对于非矩形拼图,问题会迅速变得明显,例如TOP_LEFT形状,该形状从拼图的右下侧切出.当需要重叠拼图块以将切掉的部分放在一起时,稍后添加的拼图将遮盖较早绘制的拼图.

You are overcomplicating things by trying to add JPanel puzzle pieces to your JPanel puzzle board. 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. 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.

例如,如果您尝试将TOP_LEFT件(A)和BOTTOM_RIGHT件(B)嵌套在一起.

For instance, if you try to nest a TOP_LEFT piece (A) and a BOTTOM_RIGHT piece (B) together.

 AAAAAA BBB   
 AAAAAA BBB
 AAA BBBBBB
 AAA BBBBBB

您只会看到:

+---+------+
|AAA|   BBB|
|AAA|   BBB|
|AAA|BBBBBB|
|AAA|BBBBBB|
+---+------+

重叠区域将仅由一个面板绘制. B片的整个区域(包括空白)将被绘制在第二个片的区域中,位于A片希望显示的任何内容的上方.

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.

通过将JPanel设置为透明,而不调用super.paintComponent()可以将整个组件涂成背景色,您也许可以解决此问题.但是随后您仍然必须在JPanel上绘制形状,并将JPanel正确地放置在父级JPanel上.

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. But then you still have to draw the shape on the JPanel, and position the JPanel properly on the parent JPanel.

忘记面板内的面板!只需绘制在父级JPanel上的作品.

Forget panels within panels! Just draw the pieces on the parent JPanel.

示例:

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);
    }
}

请注意,这也是最小,完整和可验证的示例.最少:无package语句;没有不使用的多余的HashSetSet导入;除了显示3个游戏片段外,不会尝试做任何其他事情.它是完整的:您可以编译并运行一个文件.这是可验证的:您可以运行它并看到它显示3个游戏片段.

Note that this is also a Minimal, Complete and Verifiable example. Minimal: No package statement; No extra HashSet and Set imports which aren't used; doesn't try to do anything except show 3 game pieces. 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.

作为奖励,它显示了Graphics2D.rotate()的工作原理,其中一件旋转了180°,另一件旋转了一个不适合您的难题的角度,但对证明旋转的效果非常有用.

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.

这篇关于Java Swing将JPanel添加到JPanel的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆