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.
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 Action
API.
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
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);
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));
}
}
Podobne pytania
Powiązane pytania
Nowe pytania
java
Java to język programowania wysokiego poziomu. Użyj tego tagu, jeśli masz problemy z używaniem lub zrozumieniem samego języka. Ten tag jest rzadko używany samodzielnie i jest najczęściej używany w połączeniu z [spring], [spring-boot], [jakarta-ee], [android], [javafx], [hadoop], [gradle] i [maven].