Slarty
Slarty

Reputation: 13

JButton Action Listener not working

I'm making a short text adventure game as my first big application, and I've run into a problem. I'm using GUI for my game, and my problem is with the action listener I'm using for the second button, proceed. All of the other code works, except for the method buttonAction. I added an action listener to proceed and whenever I run the code and click proceed, nothing happens and I can't figure out why. I moved the code now found in init2() from actionPerformed(), but it had no effect. I've also tried using @Override on buttonAction, but it gives me the error "The method buttonAction(ActionEvent) of type SimpleGui must override or implement a supertype method". Please keep in mind that my java skills are at best, elementary, so please try to explain as best you can. Any help would be greatly appreciated. The code from my application is below.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;

import Classes.Rogue;
import Classes.Warrior;
import Classes.Wizard;

public class SimpleGui extends JFrame implements ActionListener {

public JPanel panelControl, panel, panel2, panel3, panel4;
public JButton create, proceed;
public JTextField name;
public final JTextField textField = new JTextField();
public JComboBox playerClass;
public Char player1;
public String[] classOptions = { "Rogue", "Wizard", "Warrior" };
public JLabel textObject;

SimpleGui() {

    super("RPG Quest");
    name = new JTextField(20);
    init();
    this.setVisible(true);
    this.setSize(455, 250);
    this.setResizable(false);
}// end SimpleGui

public void init() {

    panel = new JPanel();
    panel3 = new JPanel();
    panel2 = new JPanel();
    playerClass = new JComboBox(classOptions);
    create = new JButton("Create Character");
    create.addActionListener(this);
    textObject = new JLabel("Name");

    panel.setBorder(BorderFactory
            .createTitledBorder("<html><font color:black>Create Your Character</font></html>"));
    panel.add(textObject);
    panel.add(name);
    panel.add(playerClass);
    panel.setBackground(Color.WHITE);

    panel3.setBorder(BorderFactory
            .createTitledBorder("<html><font color:black>Class Descriptions</font></html>"));
    panel3.add(new JLabel(
            "<html><font color:black>The Rogue has a 20% chance to land Critical Hits on enemies.</font></html>"));
    panel3.add(new JLabel(
            "<html><font color:black>The Wizard can only cast spells and has only a 70% chance of landing a hit,</font></html>"));
    panel3.add(new JLabel(
            "<html><font color:black>but spells do more damage than melee attacks.</font></html>"));
    panel3.add(new JLabel(
            "<html><font color:black>The Warrior has a 30% chance to block an incoming attack.</font></html>"));
    panel3.setBackground(Color.WHITE);

    panel2.add(create);
    panel2.setBackground(Color.WHITE);

    this.add(panel);
    this.add(panel3);
    this.add(panel2);
    this.pack();
    this.setResizable(true);
    this.setLayout(new BorderLayout());

    this.add(panel, BorderLayout.NORTH);
    this.add(panel3);
    this.add(panel2, BorderLayout.SOUTH);
}// end void

@Override
public void actionPerformed(ActionEvent event) {
    if (event.getSource() == create) {

        String type = classOptions[playerClass.getSelectedIndex()];

        if (type == "Rogue") {
            player1 = new Rogue();
        }
        if (type == "Wizard") {
            player1 = new Wizard();
        }
        if (type == "Warrior") {
            player1 = new Warrior();
        }
        player1.name = name.getText();

        JOptionPane.showMessageDialog(this, "You are a " + type
                + ". Your name is " + player1.name + ".");

        init2();
    }
}

public void init2() {

    this.remove(panel);
    this.remove(panel2);
    this.remove(panel3);

    panel.remove(textObject);
    panel.remove(name);
    panel.remove(playerClass);
    panel.setBorder(BorderFactory
            .createTitledBorder("<html><font color:black>Info</font></html>"));
    panel.setBackground(Color.WHITE);
    proceed = new JButton("Proceed");
    proceed.addActionListener(this);
    panel.add(proceed);

    textField.setText("Hello There");
    textField.setEditable(false);

    panelControl = new JPanel();
    panelControl.setBackground(Color.WHITE);
    panelControl.setBorder(BorderFactory.createBevelBorder(NORMAL));
    panelControl.add(textField);

    this.add(panelControl, BorderLayout.NORTH);
    this.add(panel, BorderLayout.SOUTH);
    this.pack();
}

public void buttonAction(ActionEvent event) {
    proceed.addActionListener(this);

    if (event.getSource() == proceed) {
        JOptionPane.showMessageDialog(this, "It Works!");
        System.out.println("hi");
    }
}
}

// end class

Upvotes: 1

Views: 2231

Answers (3)

milez
milez

Reputation: 2201

Since your class implements ActionListener, it must define an implementation for actionPerformed, which you have correctly done. Now when you say

proceed.addActionListener(this);

you are essentially connecting the button to the actionPerformed defined in your class, and not to the buttonAction() method you seem to wish to connect to. This is the same listener that create is connected to. You should be able to fix this by using

public void actionPerformed(ActionEvent event) {
if (event.getSource() == create) {

    String type = classOptions[playerClass.getSelectedIndex()];

    if (type == "Rogue") {
        player1 = new Rogue();
    }
    if (type == "Wizard") {
        player1 = new Wizard();
    }
    if (type == "Warrior") {
        player1 = new Warrior();
    }
    player1.name = name.getText();

    JOptionPane.showMessageDialog(this, "You are a " + type
            + ". Your name is " + player1.name + ".");

    init2();


} else if (event.getSource() == proceed)
{
    JOptionPane.showMessageDialog(this, "It Works!");
    System.out.println("hi");
{

}

This would make buttonAction() unnecessary. I will add that instead of implementing ActionListener, you could define listeners as inner classes, and connect buttons to them individually, making the code cleaner. Something for you to research :)

Upvotes: 2

templefox
templefox

Reputation: 505

You made the event handler be 'this', means when the button clicked, the

@Override public void actionPerformed(ActionEvent event)

will be triggered.

public void buttonAction(ActionEvent event)

is useless in your code. And you cannot use @Override on it because none of the interface have this method signature.

if (event.getSource() == create)

will only allow the create button to pass.

So, the solution can be add another condition and add your code for proceed button, in the actionPerformed method.

if (event.getSource() == create){...}
else if (event.getSource() == proceed){...}

Upvotes: 0

Blip
Blip

Reputation: 3171

You have written

proceed.addActionListener(this);

So whenever you are clicking on the JButton proceed you are basically calling actionPerformed(ActionEvent event) of the class SimpleGui. Now the actionPerformed method does not have any code for proceed. So, it does nothing.

I would here suggest that you add the code for proceed variable in the actionPerformed method of the class SimpleGui. You could add the following after the existing code of you actionPerformed as illustrated below:

@Override
public void actionPerformed(ActionEvent event) {
    if (event.getSource() == create) {
        //Your existing code;
    } else if (event.getSource() == proceed){
        //put the code for proceed action here.
    }
}

I hope that this will solve your problem.

Upvotes: 2

Related Questions