在这段代码中我有一个添加了ActionListener的jbutton(BoutonListener),但是当单击该按钮时,永远不会调用actionPerformed()方法。 我是SWING的新人,所以我可能忽略了一些重要的事情,但我不会错过这里的错误,请帮助。
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.event.*;
import java.util.*;
public class Plateau{
Fenetre f;
Modele mo;
CaseListener co;
BoutonListener li;
public Plateau(int dim){
this.f = new Fenetre(dim);
this.mo = new Modele();
this.co = new CaseListener();
this.li = new BoutonListener();
}
private class Fenetre extends JFrame{
public JPanel principale; // partie informative
public JPanel grille; // grille de jeu
public Case [][] tabs;
public int dim;
private static final String bf1 = "bf1.png";
private static final String mf1 = "mf1.png";
private static final String nf1 = "nf1.png";
private static final String bf2 = "bf2.png";
private static final String mf2 = "mf2.png";
private static final String nf2 = "nf2.png";
Container c = this.getContentPane();
JButton b = new JButton("bon"); // boutons pour ajouter les fantomes
JButton m = new JButton("mauvais");
public Fenetre(int dim){
this.dim = dim;
this.tabs = new Case[this.dim][this.dim];
c.setLayout(new GridLayout(0,2));
JPanel principale = new JPanel();
JPanel grille = new JPanel();
JLabel lab = new JLabel("Test");
principale.add(lab);
b.addActionListener(li);
m.addActionListener(li);
principale.add(b);
principale.add(m);
c.add(principale);
grille.setBackground(Color.black);
c.add(grille);
this.setVisible(true);
this.setSize(600,300);
this.setLocationRelativeTo(null);
this.setTitle("Ghosts");
grille.setLayout(new GridLayout(this.dim, this.dim));
for(int i = 0; i < this.dim ; i++){
for(int j = 0; j < this.dim ; j++){
// création de toutes les cases
tabs[i][j] = new Case();
tabs[i][j].addMouseListener(co);
tabs[i][j].setBorder(BorderFactory.createLineBorder(Color.BLACK));
grille.add(tabs[i][j]);
if( (i == 0 || i == this.dim-1) && ( j == 0 || j == this.dim-1 )){ // cases sorties
tabs[i][j].setBackground(Color.BLUE);
}
}
}
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void miseAJour(){
for(int i = 0 ; i < this.dim ; i++){
for(int j = 0 ; j < this.dim ; j++){
tabs[i][j].repaint();
}
}
}
}
private class Modele{
int total = 0;
int bj1 = 0;
int mj1 = 0;
int bj2 = 0;
int mj2 = 0;
public Case prochainePlace(){
for(int i = 0; i < f.dim ; i++){
for(int j = 0; j < f.dim ; j++){
if(j !=0 && j != f.dim - 1 && (i > f.dim-3 || (i < 2)) ){ // fantomes J1
if(f.tabs[i][j].getFantome() == null){
total++;
return f.tabs[i][j];
}
}
}
}
return null;
}
public boolean remplissable(){
return((bj1 + bj2 + mj1 + mj2) < (f.dim *2)-4 );
}
public void ajoutFantome(Case c , boolean bon){
if(total <= 8){
if(bon && bj1 < 4){
c.setFantome(new Fantome(true, Fenetre.bf1 , 2 ));
c.repaint();
bj1++;
}
if(!bon && mj1 < 4){
c.setFantome(new Fantome(false,Fenetre.mf1 , 1 ));
c.repaint();
mj1++;
}
}
else{
if(bon && bj2 < 4 ){
c.setFantome(new Fantome(true, Fenetre.bf2 , 2 ));
c.repaint();
bj2++;
}
if(!bon && mj2 < 4){
c.setFantome(new Fantome(false, Fenetre.mf2 , 2 ));
c.repaint();
mj2++;
}
}
}
}
private class BoutonListener implements ActionListener{
public void actionPerformed(ActionEvent e){
System.out.println("fonction called");
if(mo.remplissable()){
if(e.getSource() == f.b){
mo.ajoutFantome(mo.prochainePlace(), true);
f.miseAJour();
}
else{
mo.ajoutFantome(mo.prochainePlace(), false);
f.miseAJour();
}
}
}
}
private class CaseListener implements MouseListener{
public void mouseClicked(MouseEvent e){
}
public void mouseExited(MouseEvent e){
}
public void mousePressed(MouseEvent e){
}
public void mouseReleased(MouseEvent e){
}
public void mouseEntered(MouseEvent e){
}
}
}
答案 0 :(得分:3)
注意你的Plateaue构造函数:
public Plateau(int dim) {
this.f = new Fenetre(dim); // (A)
this.mo = new Modele();
this.li = new BoutonListener(); // (B)
}
你在第(A)行创建你的Fenetre JFrame,这是你将ActionListener,li添加到JButtons的地方,但你在 之后的中为一个li变量分配一个ActionListener你已经创建了JFrame。所以你真的在你的Fenetre构造函数中将空引用作为ActionListeners添加到JButtons中:
public Fenetre(int dim) {
// .... <deleted code>
// li is null here!
b.addActionListener(li);
m.addActionListener(li);
一种解决方案:反过来。
public Plateau(int dim) {
this.li = new BoutonListener(); // call this first
this.f = new Fenetre(dim);
this.mo = new Modele();
}
现在,JButtons将获取ActionListeners实例,而不是空引用。
请注意,更好的OOP兼容解决方案可能是为Fenetre提供自己的addBoutonListener(ActionListener l)
方法,您可以将监听器添加到JButton,以便您的Plateau构造函数代码可以改为:
public Plateau(int dim) {
this.f = new Fenetre(dim);
this.mo = new Modele();
f.addBoutonListener(new BoutonListener());
}
在Fenetre内,你可以:
public void addBoutonListener(BoutonListener btnListener) {
b.addActionListener(btnListener);
m.addActionListener(btnListener);
}