Swing — позиционирование некоторых JButtons

Я пытаюсь сделать небольшую игру с JButton объектами. Моя проблема в том, что когда я добавляю кнопки на свою панель, они не располагаются там, где они мне нужны. Чтобы было понятнее.

Это изображение, которое у меня есть:

введите здесь описание изображения

Вот мой код:

Мой основной класс, который расширяет JFrame, добавляет новый Board1, который расширяет JPanel

public class Main2 extends JFrame {

 public Main2() {
    setVisible(true);
    setSize(500, 500);
    add(new Board1());
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLocationRelativeTo(null);
    setTitle("Zombicide");
    setResizable(false);
 }

 public static void main(String[] args) {
    new Main2();
 }
}

Мой класс Board, который расширяет JPanel и добавляет несколько объектов Zone, которые расширяют JButton.

public class Board1 extends JPanel implements Board {

private List<Zone> zones = new ArrayList<Zone>();

  public Board1() {
    zones.add(new Zone(1, false, true, null, "/zone1D1C.jpg", 0, 0, this));
    zones.add(new Zone(2, false, false, null, "/zone2D1C.jpg", 150, 0, this));
    zones.add(new Zone(3, false, false, null, "/zone3D1C.jpg", 300, 0, this));
    zones.add(new Zone(4, true, false, null, "/zone4D1C.jpg", 0, 150, this));
    zones.add(new Zone(5, false, false, null, "/zone5D1C.jpg", 300, 150, this));
    zones.add(new Zone(6, true, false, null, "/zone6D1C.jpg", 0, 300, this));
    zones.add(new Zone(7, true, false, null, "/zone7D1C.jpg", 150, 300, this));
    zones.add(new Zone(8, false, false, null, "/zone8D1C.jpg", 300, 300, this));
  }
}

И, наконец, мой класс зоны, который расширяет JButton

public class Zone extends JButton implements ActionListener {

private final Zone zone;
private final Board board;
private Integer id;
private boolean piece;
private boolean egout;
private Integer x;
private Integer y;
private Integer x_end;
private Integer y_end;

public Zone(Integer id, boolean piece, boolean egout, Dalle[] dalles, List<Connexion> connexions, String image_name, Integer x, Integer y, Board board) {
zone = this;
addMouseListener(new TAdapter());
this.board = board;
this.piece = piece;
this.egout = egout;
this.id = id;
this.setLayout(null);
this.setBorder(null);
this.setText(null);
ImageIcon ii = new ImageIcon(this.getClass().getResource(image_name));
this.setIcon(ii);
this.x = x;
this.y = y;
this.setBounds(x, y, ii.getIconWidth(), ii.getIconHeight());
this.x_end = x + ii.getIconWidth();
this.y_end = y + ii.getIconHeight();
this.setSize(ii.getIconWidth(), ii.getIconHeight());
}

private class TAdapter extends MouseAdapter {

  @Override
  public void mouseClicked(MouseEvent e) {
    if (gotoZone()) {
      ...
    } else {
      System.out.println("error");
    }
  }
}
}

person user3734658    schedule 13.11.2014    source источник
comment
1) Чтобы быстрее получить помощь, опубликуйте MCVE (минимальный полный проверяемый пример). 2) Графические интерфейсы Java должны работать с разными ОС, размером экрана, разрешением экрана и т. д. Таким образом, они не способствуют идеальной компоновке пикселей. Вместо этого используйте менеджеры макетов или их комбинации вместе с отступами и границами макета для пробел. 3) Предоставьте ASCII-графику или простой рисунок предполагаемого макета графического интерфейса.   -  person Andrew Thompson    schedule 13.11.2014
comment
Судя по этим числам, этого можно добиться, используя 3x3 GridLayout с JLabel в центре (как невидимый компонент).   -  person Andrew Thompson    schedule 13.11.2014
comment
Я не могу использовать GridLayout, потому что это особая настольная игра. И я не хочу, чтобы между моими кнопками было место, я добавлю экран   -  person user3734658    schedule 13.11.2014
comment
И @AndrewThompson, мой код работает так, как он публикуется, за исключением импорта!   -  person user3734658    schedule 13.11.2014
comment
Рассматривали ли вы возможность использования GridBagLayout ? Вы можете избежать пробелов между кнопками и распределить кнопку по нескольким ячейкам.   -  person Fabien Thouraud    schedule 13.11.2014
comment
мой код работает так, как он опубликован Не работает здесь (или где-либо еще, где у пользователя нет этих изображений на правильном пути). Одним из способов получения изображений для примера является горячая ссылка на изображения, которые можно увидеть в этих вопросах и ответах. Также MCVE должен быть: а) полным (т. е. включать импорт) и б) одним исходным файлом.   -  person Andrew Thompson    schedule 13.11.2014
comment
@FabienThouraud Я думаю, что вы «попали в самую точку» с предложением GridBagLayout. +1   -  person Andrew Thompson    schedule 13.11.2014


Ответы (2)


GridBagLayout лучше всего подходит для того, чего вы пытаетесь достичь. Это может быть что-то вроде этого:

public class Board1 extends JPanel implements Board {
    public Board1() {
        super();
        this.setLayout(new GridBagLayout());
        GridBagConstraints constraints = new GridBagConstraints();
        constraints.fill = GridBagConstraints.HORIZONTAL;
        constraints.gridx = 0;
        constraints.gridy = 0;
        this.add(new Zone(...), constraints);
        constraints.gridx = 1;
        constraints.gridy = 0;
        this.add(new Zone(...), constraints);
        // You caught the point I think
    }
}

У вас есть хорошее руководство, созданное Oracle здесь.

person Fabien Thouraud    schedule 13.11.2014

введите здесь описание изображения

import java.awt.*;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.net.URL;

public class ZombiecideLayout {

    private JComponent ui = null;

    ZombiecideLayout() {
        initUI();
    }

    public void initUI() {
        if (ui != null) {
            return;
        }

        ui = new JPanel(new GridBagLayout());
        ui.setBorder(new EmptyBorder(4, 4, 4, 4));

        try {
            URL dayAddress = new URL("http://i.stack.imgur.com/OVOg3.jpg");
            URL nightAddress = new URL("http://i.stack.imgur.com/lxthA.jpg");
            BufferedImage biDay = ImageIO.read(
                    dayAddress).getSubimage(180, 0, 300, 300);
            BufferedImage biNight = ImageIO.read(
                    nightAddress).getSubimage(180, 0, 300, 300);

            GridBagConstraints gbc = new GridBagConstraints();
            Insets pad = new Insets(0,0,0,0);

            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.insets = pad;
            gbc.gridwidth = 1;
            gbc.gridheight = 1;
            JButton b1 = new JButton();
            b1.setContentAreaFilled(false);
            b1.setBorder(null);
            b1.setMargin(pad);
            b1.setIcon(new ImageIcon(biDay.getSubimage(0, 0, 100, 100)));
            b1.setRolloverIcon(new ImageIcon(biNight.getSubimage(0, 0, 100, 100)));
            ui.add(b1, gbc);

            gbc.gridx = 1;
            JButton b2 = new JButton();
            b2.setContentAreaFilled(false);
            b2.setBorder(null);
            b2.setMargin(pad);
            b2.setIcon(new ImageIcon(biDay.getSubimage(100, 0, 100, 100)));
            b2.setRolloverIcon(new ImageIcon(biNight.getSubimage(100, 0, 100, 100)));
            ui.add(b2, gbc);

            gbc.gridx = 2;
            JButton b3 = new JButton();
            b3.setContentAreaFilled(false);
            b3.setBorder(null);
            b3.setMargin(pad);
            b3.setIcon(new ImageIcon(biDay.getSubimage(200, 0, 100, 100)));
            b3.setRolloverIcon(new ImageIcon(biNight.getSubimage(200, 0, 100, 100)));
            ui.add(b3, gbc);

            gbc.gridx = 0;
            gbc.gridy = 1;
            gbc.gridwidth = 2;
            JButton b4 = new JButton();
            b4.setContentAreaFilled(false);
            b4.setBorder(null);
            b4.setMargin(pad);
            b4.setIcon(new ImageIcon(biDay.getSubimage(0, 100, 200, 100)));
            b4.setRolloverIcon(new ImageIcon(biNight.getSubimage(0, 100, 200, 100)));
            ui.add(b4, gbc);

            gbc.gridx = 2;
            gbc.gridy = 1;
            gbc.gridwidth = 1;
            JButton b5 = new JButton();
            b5.setContentAreaFilled(false);
            b5.setBorder(null);
            b5.setMargin(pad);
            b5.setIcon(new ImageIcon(biDay.getSubimage(200, 100, 100, 100)));
            b5.setRolloverIcon(new ImageIcon(biNight.getSubimage(200, 100, 100, 100)));
            ui.add(b5, gbc);

            gbc.gridx = 0;
            gbc.gridy = 2;
            JButton b6 = new JButton();
            b6.setContentAreaFilled(false);
            b6.setBorder(null);
            b6.setMargin(pad);
            b6.setIcon(new ImageIcon(biDay.getSubimage(0, 200, 100, 100)));
            b6.setRolloverIcon(new ImageIcon(biNight.getSubimage(0, 200, 100, 100)));
            ui.add(b6, gbc);

            gbc.gridx = 1;
            JButton b7 = new JButton();
            b7.setContentAreaFilled(false);
            b7.setBorder(null);
            b7.setMargin(pad);
            b7.setIcon(new ImageIcon(biDay.getSubimage(100, 200, 100, 100)));
            b7.setRolloverIcon(new ImageIcon(biNight.getSubimage(100, 200, 100, 100)));
            ui.add(b7, gbc);

            gbc.gridx = 2;
            JButton b8 = new JButton();
            b8.setContentAreaFilled(false);
            b8.setBorder(null);
            b8.setMargin(pad);
            b8.setIcon(new ImageIcon(biDay.getSubimage(200, 200, 100, 100)));
            b8.setRolloverIcon(new ImageIcon(biNight.getSubimage(200, 200, 100, 100)));
            ui.add(b8, gbc);

        } catch (Exception ex) {
            ex.printStackTrace();
        }

    }

    public JComponent getUI() {
        return ui;
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception useDefault) {
                }
                ZombiecideLayout o = new ZombiecideLayout();

                JFrame f = new JFrame("Zombiecide Layout");
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                f.setLocationByPlatform(true);

                f.setContentPane(o.getUI());
                f.pack();
                f.setMinimumSize(f.getSize());

                f.setVisible(true);
            }
        };
        SwingUtilities.invokeLater(r);
    }
}
person Andrew Thompson    schedule 13.11.2014
comment
Кажется, я был избит до отказа (как в названии макета, так и в ответе), но я решил опубликовать этот MCVE (раз уж он такой красивый). Конечно, оставить «галочку» там, где она сейчас. - person Andrew Thompson; 13.11.2014
comment
@FabienThouraud В SO скорость превосходит совершенство. ;) - person Andrew Thompson; 13.11.2014