Tworzę grę planszową, macierz 8X8, która ma 64 JButton sw klatce. Jak dotąd mój kod wygląda tak:

public class Main {
static JFrame f  = new JFrame();;
static JButton btn;
static JButton btnTemp;


    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setLayout((new GridLayout(8,8)));//size of the board
    f.setTitle("ex");
    f.setSize(800,800);

for (int i=0;i<=7;i++)
    {
        for (int j = 0; j<=7;j++)
        {

            btn=new JButton();
            btn = new JButton(new SoliderW());  
            btn.setName("btn"+i+""+j);
            btn.setBackground(Color.BLACK); 
            btn.addActionListener(actionListener); // make a listener to the button
            f.add(btn);
            }

    }


    f.setVisible(true);

Próbuję powiedzieć, który JButoon został kliknięty za pomocą tego kodu:

Component[] components = f.getContentPane().getComponents();


    ActionListener actionListener = new ActionListener()
    {
      @Override
        public void actionPerformed(ActionEvent e)
         {
              System.out.println("Hello");
          }
     };

       for (Component component : components)
          {
               if (component instanceof JButton)
                  {
                  ((JButton) component).addActionListener(actionListener);
                  }
          }

Nie rozumiem jednak, jak stwierdzić, który przycisk Jbutton został kliknięty.

0
Or. muha 19 grudzień 2019, 22:34
 – 
azurefrog
19 grudzień 2019, 22:36
Nie bardzo, już próbowałem
 – 
Or. muha
19 grudzień 2019, 22:40
@Or.muha, Co masz na myśli mówiąc "nie do końca". Czego próbowałeś i jaki miałeś problem? Ten link pokazuje dokładnie, jak robić to, co chcesz. Jeśli tak nie jest, musisz wyjaśnić swoje pytanie.
 – 
camickr
19 grudzień 2019, 23:51
 – 
c0der
28 grudzień 2019, 19:12

3 odpowiedzi

Zacznijmy od tego, że static nie jest twoim przyjacielem i powinieneś unikać używania go, zwłaszcza gdy próbujesz odwołać się do instancji ponad granicami obiektów.

Mógłbyś...

Użyj klas anonimowych, na przykład...

btn = new JButton();
btn = new JButton(new SoliderW());
btn.setName("btn" + i + "" + j);
btn.setBackground(Color.BLACK);
btn.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent evt) {
        // Do some work
    }
}); // make a listener to the button

Ale szczerze mówiąc, ponieważ btn to static, to ci nie pomoże

Mógłbyś...

Skorzystaj z właściwości actionCommand

ActionListener actionListener = new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent evt) {
        String command = evt.getActionCommand();
        // Do more work
    }
};

//...

for (int i = 0; i <= 7; i++) {
    for (int j = 0; j <= 7; j++) {

        btn = new JButton();
        btn = new JButton(new SoliderW());
        btn.setName("btn" + i + "" + j);
        btn.setBackground(Color.BLACK);
        // Replace the text with something that will
        // uniquely identify this button
        btn.setActionCommand("some cell identifier");
        btn.addActionListener(actionListener); // make a listener to the button
        f.add(btn);
    }

}

Mógłbyś...

Utwórz niestandardowy ActionListener, który pobiera wymagane informacje, dzięki czemu może podejmować lepsze decyzje dotyczące tego, co robić (i oddzielić je od samego przycisku)

public class CardActionListener implements ActionListener {
    private int row, col;

    public CardActionListener(int row, int col) {
        this.row = row;
        this.col = col;
    }

    @Override
    public void actionPerformed(ActionEvent arg0) {
        // Do some work...
    }
}

//...

for (int i = 0; i <= 7; i++) {
    for (int j = 0; j <= 7; j++) {

        btn = new JButton();
        btn = new JButton(new SoliderW());
        btn.setName("btn" + i + "" + j);
        btn.setBackground(Color.BLACK);
        btn.addActionListener(new CardActionListener(i, j)); // make a listener to the button
        f.add(btn);
    }

}

Mógłbyś...

I czy moje osobiste preferencje, skorzystam z ActionAPI.

Jest to podobne do ostatniej sugestii, ale tworzy znacznie bardziej samodzielną jednostkę pracy, która jest oddzielona od inwokera.

public class CardAction extends AbstractAction {
    private int row, col;

    public CardAction(int row, int col) {
        this.row = row;
        this.col = col;
        putValue(Action.LARGE_ICON_KEY, new SoliderW());
    }

    @Override
    public void actionPerformed(ActionEvent evt) {
        // Do some work...
    }
    
}

//...

for (int i = 0; i <= 7; i++) {
    for (int j = 0; j <= 7; j++) {

        btn = new JButton(new CardAction(i, j));
        f.add(btn);
    }

}

Co ważne...

Jedną z rzeczy, które staram się osiągnąć, jest oddzielenie funkcjonalności akcji od samego przycisku, aby akcja nie była zależna od przycisku, ale od tego dostarczane są informacje potrzebne do wykonywania jego operacji.

Jest to podstawowa koncepcja „kontrolera modelu-widoku” i ułatwia utrzymanie kodu

1
Community 20 czerwiec 2020, 12:12

Możesz również zrobić to w słuchaczu:

Object src = e.getSource();
if ( src instanceof JButton ) {
   System.out.println( "Button is: " + ((JButton)src).getName() );
}

Ale byłoby lepiej umieścić wszystkie przyciski w tablicy ArrayList, a następnie po prostu użyć int index = list.indexOf(src);

1
FredK 19 grudzień 2019, 23:00

Implementacja wzorca MVC zgodnie z sugestią MadProgrammer można wykonać w następujący sposób:
Mieć klasę Model, która przechowuje wszystkie informacje, których potrzebuje widok (gui).
Mieć klasę View, która używa modelu do wyświetlania gui.
Miej klasę Controller, która kontroluje model i widok.

Poniższy mre demonstruje użycie wzorca MVC do osiągnięcia wymaganej funkcjonalności.
Dla wygody i prostoty poniższy kod można skopiować i wkleić do jednego pliku o nazwie Main.java i uruchomić:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Main {

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

//used listen to changes in view
interface SelectionListener{

    void selected(int row, int column);
}

/*Model contains the information for the view and information from the view
 * as well as the logic.
 * The model is independent of the user interface.
 */
class Model {

    private final String[][] soliderNames;

    Model(int size){

        soliderNames = new String[size][size];

        for (int i=0 ; i<size  ; i++)  {
            for (int j=0; j<size ; j++) {
                soliderNames[i][j] = i+"-"+j;
            }
        }
    }

    int getNunberOfRows(){
        return soliderNames.length;
    }

    int getNunberOfColumns(){
        return soliderNames[0].length;
    }

    String getName(int row, int column) {
        return soliderNames[row][column];
    }
}

/*View only contains the user interface part*/
class View{

    private final JFrame f;
    private static final int W = 50, H = 50;

    View(Model model, SelectionListener selectionListener){

        int rows = model.getNunberOfRows();
        int cols = model.getNunberOfColumns();

        JPanel view = new JPanel(new GridLayout(rows, cols));
        for (int i=0 ; i < rows ; i++)  {
            for (int j = 0 ; j < cols ; j++)    {
                int finalI =i, finalJ = j;
                JButton btn = new JButton();
                btn = new JButton("-");
                btn.setPreferredSize(new Dimension(W,H));
                btn.setBackground(Color.BLACK);
                btn.addActionListener( a -> selectionListener.selected(finalI, finalJ));
                view.add(btn);
            }
        }

        f  = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setTitle("ex");
        f.add(view);
        f.pack();
    }

    void show(){
        f.setVisible(true);
    }
}

/* The controller controls the view and model.
 * Based on the user action, the Controller calls methods in the View and Model
 * to accomplish the requested action.
 */
class Controller implements SelectionListener {

    private static final int SIZE = 8;
    private final Model model;

    Controller(){
        model = new Model(SIZE);
        View view = new View(model, this);
        view.show();
    }

    @Override
    public void selected(int row, int column) {

        System.out.print("row: "+ row + "  column: "+ column + " clicked. ");
        System.out.println("Name is "+ model.getName(row, column));
    }
}
0
c0der 21 grudzień 2019, 11:15