Sgacedas
Sgacedas

Reputation: 27

How Can I implement an ActionListener to this?

I have this code that I am trying to modify in order to add a menu bar with 'file' etc. Adding them has been no issue, adding their listeners is proving to be an issue. Whenever I try to use the syntax fileMenu1.addActionListener(this); I get the error "Cannot use this in a static context". Any suggestions? I believe I am close to finishing this. This is a multi class program. Will put others if needed

import java.awt.Container;
import java.awt.GridLayout;
import javax.swing.*;
import java.awt.event.*;


public class BingoMain extends JFrame implements ActionListener { //I ADDED THE LISTENER HERE

    private static final int ROWS = 5;
    private static final int COLS = 5;
    private static final int MAX_BINGO = 15 * COLS;     //15*5 = 75. Max number of bingo numbers
    private static JMenuItem fileMenu1 = new JMenuItem("Play");
    private static JMenuItem fileMenu2 = new JMenuItem("Quit");
    /**
     * @param args
     *
     */
    public static void main (String[] args)  {

        //Ask for how number of players, take the input, parse it, create that many bingo cards
        String players = JOptionPane.showInputDialog(null, "How many players? (1 to 5 players)");
        int playerNums= Integer.parseInt(players);

        JFrame myBingoGUI=new JFrame(); //frame
        myBingoGUI.setSize(900, 400);
        myBingoGUI.setLocation(100, 100);
        myBingoGUI.setTitle("BINGO");
        myBingoGUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Container myContentPane = myBingoGUI.getContentPane();

        JMenuBar bar = new JMenuBar();  //create menu bar
        JMenu fileMenu = new JMenu("File"); //create the file item in the bar

        bar.add(fileMenu);

        fileMenu.add(fileMenu1);
        fileMenu.add(fileMenu2);
        myBingoGUI.setJMenuBar(bar);

        fileMenu1.addActionListener(this);     //ERROR!
        fileMenu2.addActionListener(this);     //Same error

        myContentPane.setLayout(new GridLayout(0, playerNums));

        BingoCard[] cards = new BingoCard[playerNums];
        for (int i = 0; i < cards.length; i++) {
            cards[i] = new BingoCard("Card " + (i + 1), COLS, ROWS, MAX_BINGO / COLS);
            BingoGUI bingoCard = new BingoGUI();
            cards[i].addListener(bingoCard);
            myContentPane.add(bingoCard);
        }

        myBingoGUI.setVisible(true);

        System.out.println(cards[0]);   //print the cards on the console
        System.out.println();
        /*
         *   Play the game:   
         */
        boolean winner = false;     //default false value for every player
        while (!winner) {
           String error = "";
            int calledValue = -1;
            int calledColumn=-1;
            do {
               String calledNumber = JOptionPane.showInputDialog(null, error + " Enter a BINGO call:");
                error = "";
                calledColumn = -1;
                calledValue = -1;


                /*
                 *   The first character of the input string is converted to a column number between 0 and 4
                 */
                if (Character.toUpperCase(calledNumber.charAt(0))=='B') calledColumn=0;
                if (Character.toUpperCase(calledNumber.charAt(0))=='I') calledColumn=1;
                if (Character.toUpperCase(calledNumber.charAt(0))=='N') calledColumn=2;
                if (Character.toUpperCase(calledNumber.charAt(0))=='G') calledColumn=3;
                if (Character.toUpperCase(calledNumber.charAt(0))=='O') calledColumn=4;
                if (calledColumn < 0) {
                    error = "Called Column '" + Character.toUpperCase(calledNumber.charAt(0)) + "' must be on the BINGO card";      //if first character is not a B, I, N, G, O show message
                } else {    //error catching
                    /*
                     *  The remainder of the input string is converted to an integer
                     */
                    //try catch block to catch any illegal numerical values (A legal column with an illegal value within the range will still be accepted)
                    try {
                        calledValue = Integer.parseInt(calledNumber.substring(1,calledNumber.length()));
                        if (calledValue < 1 || calledValue > MAX_BINGO) {
                            error = "Value not legal " + calledValue + " (1 <= value <= " + MAX_BINGO + ")";    //error if <0 or >75 is input, values dont exist in Bingo
                        }
                    } catch (NumberFormatException nfe) {
                        error = "Illegal number " + calledNumber.substring(1,calledNumber.length());    //error if format is wrong (i.e B9g or N5t) cant mix letters with numbers
                    }
                }
            } while (error.length() != 0);
            /*
             *   The array of called numbers is updated to show the number has been called.
             */
            for (BingoCard card : cards) {
                if (card.called(calledColumn, calledValue)) {       
                    winner = true;
                }
            }
            if (winner) {
                for (BingoCard card : cards) {
                    JOptionPane.showInputDialog(null, "BINGO");
                    card.gameOver();
                }
            }
            System.out.println(cards[0]);
            System.out.println();

        } // while

    } // main

}

Upvotes: 0

Views: 121

Answers (4)

MadProgrammer
MadProgrammer

Reputation: 347332

Basically this has no context within a static method as there is no "this" available.

Instead, you need to the instance of the class that implements ActionListener, which, oddly, you never create.

You create a class using...

public class BingoMain extends JFrame implements ActionListener {...

But you create the main frame using...

JFrame myBingoGUI=new JFrame(); //frame

Which is a better approach, but defeats the purpose of extending from JFrame.

Instead, I would recommend removing the extends JFrame portion and create an constructor to initialise the main program and then add it to the frame...

For example...

public class BingoMain implements ActionListener { //I ADDED THE LISTENER HERE

    private static final int ROWS = 5;
    private static final int COLS = 5;
    private static final int MAX_BINGO = 15 * COLS;     //15*5 = 75. Max number of bingo numbers
    private JMenuItem fileMenu1 = new JMenuItem("Play");
    private JMenuItem fileMenu2 = new JMenuItem("Quit");

    public BingoMain() {

        //Ask for how number of players, take the input, parse it, create that many bingo cards
        String players = JOptionPane.showInputDialog(null, "How many players? (1 to 5 players)");
        int playerNums= Integer.parseInt(players);

        JFrame myBingoGUI=new JFrame(); //frame
        myBingoGUI.setSize(900, 400);
        myBingoGUI.setLocation(100, 100);
        myBingoGUI.setTitle("BINGO");
        myBingoGUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        Container myContentPane = myBingoGUI.getContentPane();

        JMenuBar bar = new JMenuBar();  //create menu bar
        JMenu fileMenu = new JMenu("File"); //create the file item in the bar

        bar.add(fileMenu);

        fileMenu.add(fileMenu1);
        fileMenu.add(fileMenu2);
        myBingoGUI.setJMenuBar(bar);

        fileMenu1.addActionListener(this);     //ERROR!
        fileMenu2.addActionListener(this);     //Same error
        //...
    }

    /**
     * @param args
     *
     */
    public static void main (String[] args)  {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                BingoMain main = new BingoMain();
            }
        });

    } // main

}

Try and avoid static variables where you might want to use multiple instances of the variables

Updated

As pointed out by @peeskillet, there doesn't appear to be an implementation actionPerformed in your code example. This could simply be an oversight on your part, or the next problem you will incur...

Make sure you add

@Override
public void actionPerformed(ActionEvent evt) {
}

To your class and import java.event.ActionEvent to your imports as well...

Upvotes: 1

Christopher Francisco
Christopher Francisco

Reputation: 16308

You should probably build your interface in the constructor of the class like:

public class BingoMain extends JFrame implements ActionListener {
    public BingoMain() {
        // code to build your UI 
        fileMenu1.addActionListener(this);
        // some more code
    }

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

Upvotes: 0

AgilePro
AgilePro

Reputation: 5614

    fileMenu1.addActionListener(this);     //ERROR!
    fileMenu2.addActionListener(this);     //Same error

The main method is a static method, and there is no this in a static context. You have to create an instance of your BingoMain class, and pass an instance of that class in.

Upvotes: 0

Kevin Bowersox
Kevin Bowersox

Reputation: 94499

The code should make an instance of BingoMain. The main method is static which means it is not associated with any instance of the class. The keyword static indicates the method, field, etc is associated with the class itself and not instances of the class. The code incorrectly assumes that the static main method can refer to an instance of the class itself, which is not possible since its static.

 public static void main (String[] args)  {
        /* Omitted*/
        BingoMain main = new BingoMain();
        fileMenu1.addActionListener(main);     //NO ERROR!

        /* Omitted*/
}

Upvotes: 2

Related Questions