[英]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
不是您的朋友开始,您应该避免使用它,尤其是当您尝试跨对象边界引用实例时。
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但是,老实说,因为
btn
是static
,这不会帮助你
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);
}
}
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);
}
}
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);
}
}
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.