Центрирование игровых фигур, которые не поддерживают размер при изменении размера - PullRequest
0 голосов
/ 05 сентября 2018

У меня есть настольная игра (например, «Монополия»), в которой на одной клетке можно разместить несколько игровых фигур. Я нарисовал 4 круга на зеленом фоне, но круги не центрированы, и когда я изменяю их размер, круги перемещаются по всему месту, а не остаются с плиткой.

CirclePanel:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;

import javax.swing.JPanel;

@SuppressWarnings("serial")
public class CirclePanel extends JPanel {
    public static final Dimension SIZE = new Dimension(35, 35);

    public CirclePanel() {
    }

    @Override
    protected void paintComponent(Graphics g) {
        g.setColor(Color.RED);
        g.fillOval(0, 0, 35, 35);
        System.out.println(getSize());
    }

    @Override
    public Dimension getPreferredSize() {
        return SIZE;
    }
}

GraphicsTile:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;

@SuppressWarnings("serial")
public class GraphicsTile extends JPanel {
    public static final Dimension SIZE = new Dimension(140, 140);
    public static final GridLayout MGR = new GridLayout(2, 2);

    public GraphicsTile() {
        super();
        setLayout(MGR);

        add(new CirclePanel());
        add(new CirclePanel());
        add(new CirclePanel());
        add(new CirclePanel());

    }

    @Override
    public Dimension getPreferredSize() {
        return SIZE;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.GREEN);
        g.fillRect(0, 0, 140, 140);
    }
}

GraphicsRunner:

import java.awt.Dimension;
import java.awt.GridLayout;

import javax.swing.JFrame;

public class GraphicsRunner {

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setLayout(new GridLayout(4, 0, 5, 5));

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(1280, 720);
        frame.setPreferredSize(new Dimension(140, 140));
        frame.add(new GraphicsTile());
        frame.add(new GraphicsTile());
        frame.setVisible(true);
    }
}

Ответы [ 2 ]

0 голосов
/ 06 сентября 2018

Еще раз, не играйте с размером. Все компоненты Swing должны определять свой собственный предпочтительный размер. Это включает в себя панели и рамы.

Размер панели будет определяться на основе компонента, добавленного на панель.

Рамка будет определять ее размер на основе панелей, добавленных в рамку. После добавления панелей вы используете метод pack ().

Тогда все компоненты будут отображаться в их предпочтительном размере. Затем вы можете просто сделать кадр фиксированного размера, используя:

frame.setResizable( false );

Однако, если вы не сделаете вышеизложенное, вам нужно определить, что произойдет, если размер кадра будет изменен. Затем вам нужно быть более внимательным к менеджерам компоновки, которые вы используете.

Для GridLayout размеры всех компонентов изменяются, чтобы заполнить все доступное пространство. Это легко проверить, изменив код рисования в GraphicsTile` на:

//g.fillRect(0, 0, 140, 140);
g.fillRect(0, 0, getWidth(), getHeight());

Это лучшая техника рисования. Вы не должны быть жесткими значениями. Используйте свойства компонента, чтобы при необходимости указать параметры.

Если вы сделаете это, вы увидите, что плитки расширяются, чтобы заполнить область, и CirclePanel находится в начале GraphicsTile (опять же, потому что вы жестко закодировали местоположение).

Чтобы не допустить увеличения размера GraphicsTile, вам нужно будет обернуть его в другую панель, которая учитывает предпочтительный размер добавляемых к нему компонентов.

Простой способ сделать это - использовать GridBagLayout со значением по умолчанию GridBagConstraints. Теперь любой компонент, добавленный к нему, будет центрирован в доступном пространстве.

Таким образом, реструктуризация вашего метода main () будет выглядеть так:

JFrame frame = new JFrame();
frame.setLayout(new GridBagLayout());

JPanel tilePanel = new JPanel( new GridLayout(0, 1, 5, 5) );
tilePanel.add(new GraphicsTile());
tilePanel.add(new GraphicsTile());

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(tilePanel, new GridBagConstraints());
frame.pack();
frame.setVisible(true);
0 голосов
/ 06 сентября 2018

Это потому, что GridLayout автоматически расширяет содержимое, используя все доступное пространство.

Этого можно избежать, обернув GraphicsTiles другим JPanel (который по умолчанию использует FlowLayout). Таким образом GridLayout будет вынужден оставаться внутри оболочки.

Например, в GraphicsRunner вы можете использовать panel в качестве оболочки:

JPanel panel = new JPanel();
panel.add(new GraphicsTile());
frame.add(panel);

panel = new JPanel();
panel.add(new GraphicsTile());
frame.add(panel);

Но вы, возможно, захотите выяснить, подходят ли другие макеты (или вообще не используют макеты) к вашим потребностям.

Здесь похожий вопрос, который может помочь: Как установить размер компонента с помощью GridLayout? Есть ли лучший способ?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...