Это связано с Как получить X и Y индекс элемента внутри сообщения GridLayout? и ответы на него.

По какой-то причине никто из них не предлагал расширить JButton, чтобы включить его положение в сетке и в связанный массив кнопок.

Я сделал следующую иллюстрацию, которая просто отображает координаты кнопки при нажатии.

Расширенный JButton:

package buttons_array;

import javax.swing.*;

@SuppressWarnings("serial")
public class ButtonWithCoordinates extends JButton {

    int coordX;
    int coordY;

    public ButtonWithCoordinates(String buttonText, int coordX, int coordY) {
        super(buttonText);
        this.coordX = coordX;
        this.coordY = coordY;
    }

    /**
     * @return the coordX
     */
    public int getCoordX() {
        return coordX;
    }

    /**
     * @return the coordY
     */
    public int getCoordY() {
        return coordY;
    }
}

Пример графического интерфейса:

package buttons_array;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class ButtonsArray implements ActionListener {

    private ButtonWithCoordinates buttons[][];
    private int nRows;
    private int nCols;

    private JFrame frame;
    private JPanel panel;

    public ButtonsArray(int x, int y) {
        if (x > 0 && y > 0) {
            nRows = x;
            nCols = y;
            buttons = new ButtonWithCoordinates[nRows][nCols];
            for (int i=0; i < nRows; ++i) {
                for (int j=0; j < nCols; ++j) {
                    buttons[i][j] = new ButtonWithCoordinates("        ", i, j);
                    buttons[i][j].addActionListener(this);
                }
            }
        } else {
            throw new IllegalArgumentException("Illegal array dimensions!!!");
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {

        // TODO Auto-generated method stub
        ButtonWithCoordinates button = (ButtonWithCoordinates) e.getSource();
        button.setText(button.getCoordX() + ", " + button.getCoordY());

    }

    public void GUI() {

        if (buttons == null) { throw new NullPointerException("Array is not initialized!!!"); }

        frame = new JFrame();
        panel = new JPanel();

        frame.setContentPane(panel);
        panel.setLayout(new GridLayout(nRows, nCols));
        for (int i=0; i < nRows; ++i) {
            for (int j=0; j < nCols; ++j) {
                panel.add(buttons[i][j]);
            }
        }

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);

    }

    public static void main(String[] args) {

        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new ButtonsArray(3, 5).GUI();
            }
        });         

    }

}

Теперь мои вопросы:

  1. Не изобретал ли я здесь велосипед? Я имею в виду, есть ли более простой способ добиться того же?

  2. Это чем-то хуже, чем поиск в массиве каждый раз, когда нам нужно найти координаты?

3
PM 77-1 25 Янв 2014 в 07:35
Будут ли ваши пуговицы иметь одинаковую ширину?
 – 
Paul Richter
25 Янв 2014 в 08:42
2
Это неуместное подклассирование: а) нет новой функциональности, которая развивает его функциональность б) очень хрупкая - класс должен полностью контролировать гарантии своих ограничений, а ваш компьютер не может, потому что это кто-то другой добавляет его в сетку в) там есть несколько способов легко достичь того же без подкласса d) ...
 – 
kleopatra
25 Янв 2014 в 15:00
- Да, если используется GridLayout.
 – 
PM 77-1
26 Янв 2014 в 00:52
1
- b - позволяет использовать либо GridLayout, либо GridBagLayout; c - хотите привести примеры?
 – 
PM 77-1
26 Янв 2014 в 00:54

1 ответ

Лучший ответ

Исходная версия этого примера использованное расширение:

GridButton extends JButton

Обновленная версия была основана на беседе, которую видели здесь. Хотя расширение может быть подходящим в некоторых контекстах, несколько альтернатив упоминаются здесь; недвижимость клиента особенно удобна. Идентифицировать кнопку по координатам сетки также легко:

private static final int N = 5;
List<JButton> list = new ArrayList<>();
…
private JButton getGridButton(int r, int c) {
    int index = r * N + c;
    return list.get(index);
}
1
Community 23 Май 2017 в 15:07
1
Спасибо за очень информативный ответ. Итак, какой подход вы лично считаете наиболее подходящим при работе с массивом некоторых потомков JComponent? У меня также есть один не связанный вопрос. В своем примере вы использовали EventQueue.invokeLater(...). Учебники, которые я видел, хотят, чтобы мы использовали SwingUtilities.invokeLater(...). Один больше подходит, чем другой?
 – 
PM 77-1
26 Янв 2014 в 01:08
SwingUtilities.invokeLater() "просто прикрытие для java.awt.EventQueue.invokeLater()". По дизайну см. Bloch, op cit. , особенно пункты 16 и 17.
 – 
trashgod
26 Янв 2014 в 03:29