简体   繁体   English

检查哪个 Jbutton(多个 Jbuttons)被点击

[英]Checking which Jbutton (of multiple Jbuttons) was clicked

I am making a board game, 8X8 matrix that have 64 JButton s in a frame.我正在制作一个棋盘游戏,一个框架中有 64 个JButton的 8X8 矩阵。 So far my code goes like this:到目前为止,我的代码是这样的:

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);

I am trying to tell which JButoon was clicked using this code:我正在尝试使用以下代码判断点击了哪个 JButoon:

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);
                  }
          }

Yet, I dont understand how to tell which Jbutton was clicked.然而,我不明白如何判断哪个 Jbutton 被点击。

Let's start with static is not your friend and you should avoid using it, especially when you're trying to reference an instance across object boundaries.让我们从static不是您的朋友开始,您应该避免使用它,尤其是当您尝试跨对象边界引用实例时。

You could...你可以...

Use Anonymous Classes , for example...使用匿名类,例如...

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

But, to be honest, since btn is static , this isn't going to help you但是,老实说,因为btnstatic ,这不会帮助你

You could...你可以...

Make use of the actionCommand property使用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);
    }

}

You could...你可以...

Create a custom ActionListener which takes the required information so that it can make better decisions about what to do (and decouple it from the button itself)创建一个自定义ActionListener ,它获取所需的信息,以便它可以更好地决定要做什么(并将其与按钮本身分离)

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);
    }

}

You could...你可以...

And would my personal preference, make use of the Action API .我个人的喜好是否会使用Action API

This is similar to the last suggestion, but creates a much more self contained unit of work, which is decoupled from the invoker.这类似于最后一个建议,但创建了一个更加独立的工作单元,它与调用程序分离。

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);
    }

}

What's important...什么重要...

One of the things I'm trying towards is decoupling the action functionality from the button itself, so the action isn't dependent on the button, but on the is provided the information it needs to perform it's operations.我正在尝试的一件事是将操作功能与按钮本身分离,因此操作不依赖于按钮,而是提供了执行操作所需的信息。

This is a core concept of "model-view-controller" and will make you code easier to maintain这是“模型-视图-控制器”的核心概念,将使您的代码更易于维护

You could also do this in the listener:您也可以在侦听器中执行此操作:

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

But it would be better to put all of the buttons in an ArrayList and then just use int index = list.indexOf(src);但是最好将所有按钮放在一个 ArrayList 中,然后只使用int index = list.indexOf(src);

Implementing MVC Pattern as suggested by MadProgrammer can be done as follows:可以按照MadProgrammer 的建议实现MVC 模式,如下所示:
Have a Model class that holds all the information that the view (gui) needs.有一个Model类,其中包含视图 (gui) 需要的所有信息。
Have a View class that uses the model to displays gui.有一个使用模型来显示 gui 的View类。
Have a Controller class that controls the model and view.有一个Controller模型和视图的Controller类。

The following mre demonstrates the use of MVC Pattern to achieve the functionality required.下面的mre演示了使用 MVC 模式来实现所需的功能。
For convenience and simplicity, the following code can be copy-pasted into one file called Main.java and run:为了方便和简单,可以将以下代码复制粘贴到一个名为Main.java文件中并运行:

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));
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM