Java Swing Добавить JPanel в JPanel - PullRequest
0 голосов
/ 05 марта 2019

Ситуация

В настоящее время я пытаюсь построить 2D-игру с помощью Java Swing.Для этого у меня есть основной класс Puzzle, который является подклассом JFrame.К моей рамке я добавляю свой основной JPanel, который состоит из нескольких JPanel, добавленных вместе (каждый из которых является новой частью).

РЕДАКТИРОВАТЬ 2: PlayingField - это моймодель, которая будет хранить текущее местоположение каждого куска.Можно выделить кусок мышью (план состоит в том, чтобы выделить его) и перемещать его с помощью клавиш со стрелками, пока следующий шаг (полная ячейка, т.е. около 100 пикселей) не является местоположением одного из другихкуски.На данный момент 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);
}

Приведенный выше метод создаст мой фрейм и добавит главную панель.Следующий метод - это моя основная панель, которая добавляет к себе несколько 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);
}

Каждый GamingPiece или, точнее, мои под JPanel рисуют базовую часть (я рисую только одну ивращая остальные, так как все состоит из одной и той же произвольной формы).Класс 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);
}

Проблема и мои вопросы

Поскольку я довольно новичок в Java, ядействительно не знаю, как это сделать правильно.Если я добавлю свои части, создав новый объект и добавив его на главную панель, он не покажет все из них, только последний добавленный.Некоторые, кажется, даже не работают, даже если они добавлены единственными (чтобы объяснить мою ситуацию: у меня есть фигуры, которые имеют одинаковую произвольную форму, просто вращаются по-разному, но использование Graphics2D#rotate(), похоже, не работает нормально).

Надеюсь, я объяснил свою ситуацию и мою проблему достаточно хорошо, чтобы вы, ребята, помогли мне.Заранее спасибо!

РЕДАКТИРОВАТЬ:

Мои коды

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 другие классы не участвуют.

1 Ответ

0 голосов
/ 05 марта 2019

Вы слишком усложняете вещи, пытаясь добавить JPanel кусочки головоломки на вашу JPanel доску головоломок.Проблемы быстро станут очевидными с вашими непрямоугольными кусочками головоломки, такими как фигура TOP_LEFT, у которой есть вырез в нижней правой части фигуры.Когда приходит время перекрывать части головоломки, чтобы совмещать вырезанные части, добавленная позже часть будет перекрывать ранее нарисованные части.

Например, если вы попытаетесь вложить часть TOP_LEFT (A) ичасть BOTTOM_RIGHT (B) вместе.

 AAAAAA BBB   
 AAAAAA BBB
 AAA BBBBBB
 AAA BBBBBB

Вы увидите только:

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

Область перекрытия будет нарисована только одной из панелей.Вся область фрагмента B, включая пустое пространство, будет нарисована в области второго фрагмента, поверх того, что фигура A надеялась отобразить.

Вы можете обойти это,установив прозрачность JPanel, и не вызывая super.paintComponent(), который окрашивает весь компонент в цвет фона.Но тогда вам все равно нужно нарисовать фигуру на JPanel и правильно расположить JPanel на родительском JPanel.

Забудьте о панелях внутри панелей!Просто нарисуйте кусочки на родительском 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);
    }
}

Обратите внимание, что это также пример Minimal, Complete и Verifiable.Минимальный: Нет package оператор;Нет дополнительных HashSet и Set импортов, которые не используются;не пытается ничего делать, кроме как показать 3 игровых фрагмента.Все готово: один файл вы можете скомпилировать и запустить.Это можно проверить: вы можете запустить его и увидеть 3 игровых фигуры.

В качестве бонуса показано, как работает Graphics2D.rotate(), одна часть повернута на 180 °, а другая повернута на угол, который не подходитдля вашей загадки, но полезно для демонстрации того, что вращение работает просто отлично.

...