Adding ActionListener to JButtons - java

When attempting to implement ActionListener I receive the following error
EmployeesApplet.java:5: error: EmployeesApplet is not abstract and does not override
abstract method actionPerformed(ActionEvent) in ActionListener
public class EmployeesApplet extends JApplet implements ActionListener
^
1 error
I do not want to make EmployeesApplet abstract since it doesn't need to be.
My code is below, note I commented out the implements ActionListener and adding the JButtons as ActionListener
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class EmployeesApplet extends JApplet //implements ActionListener
{
public JButton sd = new JButton ("Salaried");
public JButton hr = new JButton ("Hourly");
public JButton cm = new JButton ("Commissioned");
public JButton cl = new JButton ("Clear");
private final int FIELDS = 8,
FIELD_WIDTH = 20;
private String[] strings = new String[FIELDS];
private TextFieldWithLabel[] tf = new TextFieldWithLabel[FIELDS];
private JTextArea ta = new JTextArea(5,25);
public void init()
{
String[] s = {"First Name", "Last Name", "Employee ID", "(a) Salaried: Weekly Salary", "(b1) Hourly 1: Rate Per Hour",
"(b2) Hourly 2: Hours Worked" , "(c1) Commissioned: Rate", "(c2) Commissioned: Gross Sales" };
//----------------------
// Set up the Structure
//----------------------
Container c = getContentPane();
JPanel f = new JPanel(new FlowLayout());
JPanel b = new JPanel(new BorderLayout(2,0));
JPanel glb = new JPanel(new GridLayout(8,1,0,2));
JPanel gtf = new JPanel(new GridLayout(8,1,0,2));
JPanel flb = new JPanel(new FlowLayout());
// Add FlowLayout to the container
c.add(f);
// Add BorderLayout to the FlowLayout
f.add(b);
//---------------------------------------
//Add JPanels to the BorderLayout regions
//---------------------------------------
// Add JLables to GridLayout in West
b.add(glb, BorderLayout.WEST);
for (int i = 0; i < tf.length; i++)
{
tf[i] = new TextFieldWithLabel(s[i], FIELD_WIDTH);
glb.add(tf[i].getLabel());
}
// Add JTextFeilds to GridLayout in East
b.add(gtf, BorderLayout.EAST);
for (int i = 0; i < tf.length; i++)
{
tf[i] = new TextFieldWithLabel(s[i], FIELD_WIDTH);
tf[i].getTextField();
gtf.add(tf[i].getTextField());
}
// Add JButtons to FlowLayout in South
b.add(flb, BorderLayout.SOUTH);
flb.add(sd);
flb.add(hr);
flb.add(cm);
flb.add(cl);
//sd.addActionListener(this);
//hr.addActionListener(this);
//cm.addActionListener(this);
//cl.addActionListener(this);
// Add JTextArea and make it not editable
f.add(ta);
ta.setEditable(false);
}
public void readFields()
{
}
public void fieldsExist()
{
}
public void fieldsEmpty()
{
}
public void actionPerformed()
{
}
}

Your actionPerformed method needs an ActionEvent as it's parameter:
public void actionPerformed(ActionEvent e) {
}
Otherwise you won't be overriding the method defined in ActionListener - you'll just be creating a new method. Since ActionListener is an interface, you are required to implement all the methods defined in the interface, hence the error.
The actionPerformed method is declared with the ActionEvent parameter to pass the method details about the event (which component triggered the event, the action command, etc..). Without the ActionEvent parameter, there is no easy way to gather such information. When an action is performed, an ActionEvent object is created, filled with the event information, then your actionPerformed method is invoked, which the ActionEvent object is passed in as an argument.

Your class is implementing the interface ActionListener
hence you have 2 options... make the class abstract or implement the method actionPerformed
the first one looks like what you need....
so try doing something like:
public class EmployeesApplet extends JApplet implements ActionListener {
....
....
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}

Related

How do you have an ActionListener perform different events based on the actionPerformed?

I have four buttons each on four different panels. If I press the button I would want the panel it's on to change color. The problem is I only know how to do that for one button and not all four. Here is my code so far...
public class tester implements ActionListener
{
JPanel B;
JPanel A;
public static void main(String[]args)
{
new tester();
}
public void tester()
{
JFrame test = new JFrame("tester:");
B = new JPanel();
A= new JPanel();
JPanel cc = new JPanel();
JPanel dd = new JPanel();
JButton b = new JButton("ButtonB");
JButton a = new JButton("ButtonA");
JButton c = new JButton("ButtonC");
JButton d = new JButton("ButtonD");
test.setLayout(new GridLayout(2,2));
test.setSize(600,500);
B.setBackground(Color.BLUE);
A.setBackground(Color.RED);
cc.setBackground(Color.BLACK);
dd.setBackground(Color.WHITE);
B.add(b);
A.add(a);
cc.add(c);
dd.add(d);
test.add(A);
test.add(B);
test.add(cc);
test.add(dd);
test.setVisible(true);
b.addActionListener(this);
a.addActionListener(this);
}
public void actionPerformed(ActionEvent e)
{
B.setBackground(Color.PINK);
}
}
You can use anonymously created Action listeners instead of implementing interface in your class.
b.addActionListener(new ActionListener() {
//method impl.
});
And use that to create 4 different actions.
Or you could get source of action from
e.getSource()
And then decide based on that.
Or you can skip ActionListener all the way, and use lambda
b.addActionListener(e -> someActionOrSomething(e))
You have to check the resource and can perform action based on it If you are trying to keep a common ActionListener,
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==b)//button b
B.setBackground(Color.PINK);
else if(e.getSource()==a)//button a
A.setBackground(Color.BLACK);
}
Please note you have to declare your buttons globally, If you have to use it inside the class,
public class Test implements ActionListener
{
JPanel B;
JPanel A;
JButton b;
JButton a;
Also you have created the implementation in a method called tester which should be called as,
new Test().tester();

JComboBox actionListener doesn't function

I have a class that has 4 private attributes, and through a JComboBox selection, I want to modify them through calling a procedure. However, it seems like even though the JComboBox appears with the selection, the attributes that are shown don't change.
public class PanneauVehicule extends JPanel {
private String[] vehicules;
private int majCarburant;
private int majPassager;
public class PanneauVehicule extends JPanel {
//Main constructor
public PanneauVehicule(){
//Creates a JPanel
super();
//Sets layout as BorderLayout
setLayout(new BorderLayout());
initListeVehicule();
initLabels();
}
public void initListeVehicule(){
vehicules = new String[] {Constantes.CS100 , Constantes.CS300 ,
Constantes.GREYHOUND102D3 , Constantes.GREYHOUNDG4500 ,
Constantes.TGVATLANTIQUE , Constantes.TGVDUPLEX};
final JComboBox<String> vehiculesList = new JComboBox<>(vehicules);
//Keep in mind the comboBox does appear with the right selections
add(vehiculesList,BorderLayout.NORTH);
//Here's where it doesnt work.
vehiculesList.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
majInfo(2,4);
}
});
}
public void majInfo(int test1, int test2){
this.majCarburant = test2;
this.majPassager = test1;
}
public void initLabels(){
JPanel panneauBas = new JPanel();
panneauBas.setLayout(new GridLayout(2,1,5,5));
JLabel labelCarburant = new JLabel();
labelCarburant.setText("Type de caburant: " + this.majCarburant);
JLabel labelPassagers = new JLabel();
labelPassagers.setText("Nb de passagers: " + this.majPassager);
panneauBas.add(labelPassagers);
panneauBas.add(labelCarburant);
add(panneauBas, BorderLayout.SOUTH);
panneauBas.setBackground(Color.WHITE);
}
After that, I use another procedure that will make majCarburant and majPassager appear on screen. However their values are shown as default (0). I can make their values change manually without using an ActionListener, but the task at hand requires me to use one.
I've been trying ways to just simply change the values through actionListener directly,
You don't invoke an ActionListener directly. Once an ActionListener has been added to the combo box, you can invoke:
setSelectedItem(...) or
setSelectedIndex(...)
on the combo box and the combo box will invoke the ActionListener.
I found the solution after a few more hours of meddling. I just integrated the procedure that creates labels into initListeVehicule, and from there the ActionListener can access the labels to modify their texts.
public void initListeVehiculeInfos(){
vehicules = new String[] {Constantes.CS100 , Constantes.CS300 ,
Constantes.GREYHOUND102D3 , Constantes.GREYHOUNDG4500 ,
Constantes.TGVATLANTIQUE , Constantes.TGVDUPLEX};
final JComboBox<String> vehiculesList = new JComboBox<>(vehicules);
add(vehiculesList,BorderLayout.NORTH);
JPanel panneauBas = panelGenerator();
//these setTexts serve as default values before doing your first selection
final JLabel carb = labelGenerator();
carb.setText("Carburant: Kérosène");
final JLabel passager = labelGenerator();
passager.setText("Nb Passager: 110");
vehiculesList.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e){
InterfaceVehicules info = FabriqueVehicule.obtenirVehicule(vehiculesList.getSelectedIndex());
carb.setText("Carburant: " + info.tabNomTypeCarburant[info.getTypeCarburant()] );
passager.setText("Nb Passagers: " + info.getNbPassagersMax());
}
});
panneauBas.add(carb);
panneauBas.add(passager);
add(panneauBas, BorderLayout.SOUTH);
}

Remove parent JPanel when JButton is clicked

I have a ArrayList of JPanel. And each items of this list has a JButton.
Now, when JButton is clicked I want to remove its' parent JPanel from the ArrayList. So how can I make the JButton remove its' parent from the ArrayList?
Thanks in advance.
public class TestingArrayList extends JFrame {
JPanel grandPanel; // a JPanel for all the panels
ArrayList<JPanel> panelParent = new ArrayList<>(); // JPanel ArrayList
public TestingArrayList() {
super("Test");
setLayout(new FlowLayout());
grandPanel = new JPanel();
add(grandPanel);
for (int i = 0; i < 10; i++) { // adding 10 JPanel into grandPanel
panelParent.add(new JPanel());
grandPanel.add(panelParent.get(i));
// adding JButton in all panels
JButton btnParent = new JButton("X");
panelParent.get(i).add(btnParent);
// add new task button action
btnParent.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
System.out.println(getParent());
//What to do!!!
}
});
}
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(1000, 100);
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
new TestingArrayList();
}
}
You have all you need right in your code. You just need a final reference to the JPanel of interest as this will allow you to use it within the anonymous inner ActionListener class:
for (int i = 0; i < 10; i++) {
// make it final so that it is accessible from inner anon class
final JPanel myPanel = new JPanel();
panelParent.add(myPanel);
grandPanel.add(myPanel);
JButton btnParent = new JButton("X");
myPanel.add(btnParent);
btnParent.addActionListener(event -> panelParent.remove(myPanel));
}
If you also want to remove it from the grandPanel, then you'll need more...
btnParent.addActionListener(event -> {
panelParent.remove(myPanel);
grandPanel.remove(myPanel);
grandPanel.revalidate();
grandPanel.repaint();
});
Note, that if you wanted to use Seymore's method of removing the JPanel, you first need to understand that the source object obtained by calling getSource() on the ActionEvent parameter is the object that the listener was added to -- here a JButton not a JPanel, and also the type of object returned is Object, and so no Swing component methods can be called on it without casting. And so you would need to wrap all in parenthesis in order to allow you to call methods of that type. For example:
parentPanel.remove((JPanel) ((JButton) event.getSource()).getParent());
or
parentPanel.remove((JPanel) ((JComponent) event.getSource()).getParent());
I find it easier to separate lines when code gets this convoluted:
// since a JButton extends from JComponent
JComponent source = (JComponent) event.getSource();
JPanel parent = (JPanel) source.getParent();
parentPanel.remove(parent);
btnParent.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
System.out.println(getParent());
panelParent.remove((JPanel)(event.getSource().getParent()));
}
});

Class Diagram from my code

I used a plug-in of Eclipse to create the class diagram of this code:
public class ButtonGrid
{
private static int difficulty, moveleft, Counter, treasure_x , treasure_y;
private static String message;
JTextField tf = new JTextField();
public static JTextField tf2 = new JTextField();
JFrame frame = new JFrame(); //creation of the main game window
JPanel panel = new JPanel();
JPanel panel2 = new JPanel(new FlowLayout());
JPanel panel3 = new JPanel();
JLabel hint = new JLabel("Hint:");
JButton[][] grid; //grid buttons
public ButtonGrid (int width, int length)
{
}
ActionListener al = new ActionListener() //Action listener for the buttongrid
{
public void actionPerformed(ActionEvent e)
{
}
};
ActionListener al2 = new ActionListener() // Action listener for the reset button
{
public void actionPerformed (ActionEvent e)
{
}
}
};
public static void main (String[] args)
{
}
I cut some useless parts to reduce the size. The diagram that Eclipse draw is this one:
Do you think it's correct? I'm wondering because i thougth the ActionListeners were considered sub-classes, and also the ActionListener in the main method is not showed, but maybe it's just me not understanding how class diagrams work.
It looks right to me. The ActionListeners you have defined are anonymous classes for your protected attributes a1, and a2. Basically what the anonymous classes are doing is subclassing the ActionListener class. These new, unnamed classes are set to a1, and a2. That is why they show up the way they do in the class diagram. Also the reason that the one in your main method isn't showing up, is that anonymous ActionListener is a local variable to your main function.
Here is some information that Oracle: has about anonymous classes (http://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html)
Hope this help, good luck with your programming.
Your diagram seems correct. None of the variables you create inside the methods will appear in this diagram. Only the variables you define on the top (or outside the methods but inside the class definition) will appear in the diagram:
private static int difficulty, moveleft, Counter, treasure_x , treasure_y;
private static String message;
JTextField tf = new JTextField();
public static JTextField tf2 = new JTextField();
JFrame frame = new JFrame(); //creation of the main game window
JPanel panel = new JPanel();
JPanel panel2 = new JPanel(new FlowLayout());
JPanel panel3 = new JPanel();
JLabel hint = new JLabel("Hint:");
JButton[][] grid; //grid buttons
ActionListener al = new ActionListener() //Action listener for the buttongrid
{
//defintion of this ActionListner
};
ActionListener al2 = new ActionListener() // Action listener for the reset button
{
//definition of this ActionListener
};
ActionListener is actually an interface:
http://docs.oracle.com/javase/7/docs/api/java/awt/event/ActionListener.html
You must define it or else you can't use it. A subclass is a class that has a parent class:
http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

Problems with getText() from JTextField

I'm having troubles with the .getText() command trying to retrieve data from a JTextField. I've been looking for the solution but couldn't find it. Is there anybody who can see what I'm doing wrong?
What I'm trying is to make is a bouncing ball which parameters such as elasticity, gravity and initial speed can be changed.
When trying to compile the following message appears:
ERROR in BBPanel.java (at line 88) String gravityIn = gravity_input.getText();
gravity_input cannot be resolved
Thanks!
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/////////////////////////////////////////////////////////////////// BBPanel
class BBPanel extends JPanel {
BallInBox n_bb; // The bouncing ball panel
//========================================================== constructor
/** Creates a panel with the controls and bouncing ball display. */
BBPanel() {
//... Create components
n_bb = new BallInBox();
JButton startButton = new JButton("Start");
JButton stopButton = new JButton("Stop");
JButton resetButton = new JButton("Reset");
JButton gveButton = new JButton("GetData");
JLabel gravityLbl = new JLabel (" set gravity " );
JLabel velocity_yLbl = new JLabel (" set initial y-dir speed " );
JLabel elasticityLbl = new JLabel (" set elasticity [0-100%]" );
JTextField gravity_input = new JTextField(20);
JTextField velocity_y_input = new JTextField(20);
JTextField elasticity_input = new JTextField(20);
//... Add Listeners
startButton.addActionListener(new StartAction() );
stopButton.addActionListener(new StopAction() );
resetButton.addActionListener(new ResetAction() );
gveButton.addActionListener(new DataAction() );
//... Layout inner panel with three buttons horizontally
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout());
buttonPanel.add(startButton);
buttonPanel.add(stopButton);
buttonPanel.add(resetButton);
//
JPanel variablePanel = new JPanel();
variablePanel.setLayout(new GridLayout(0,2));
variablePanel.add(gravityLbl);
variablePanel.add(gravity_input);
variablePanel.add(velocity_yLbl);
variablePanel.add(velocity_y_input);
variablePanel.add(elasticityLbl);
variablePanel.add(elasticity_input);
variablePanel.add(gveButton);
//... Layout outer panel with button panel above bouncing ball
this.setLayout(new BorderLayout());
this.add(buttonPanel , BorderLayout.NORTH);
this.add(n_bb , BorderLayout.CENTER);
this.add(variablePanel, BorderLayout.EAST);
}//end constructor
////////////////////////////////////// inner listener class StartAction
class StartAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
n_bb.setAnimation(true);
}
}
//////////////////////////////////////// inner listener class StopAction
class StopAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
n_bb.setAnimation(false);
}
}
///////////////////////////////////////// inner listener class ResetAction
class ResetAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
n_bb.resetAnimation(true);
}
}
////////////////////////////////////////// inner listener class GravityAction
class DataAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
String gravityIn = gravity_input.getText();
//System.out.println(gravityIn);
n_bb.setData(true);
}
}
}//endclass BBPanel
The variable gravity_input is only defined locally in the scope of the constructor of BBPanel. You need to make it a class member variable if you wish to make it visible to your DataAction class.
public class BBPanel extends JPanel {
private JTextField gravity_input; // to be initialized...
...
Side note:
Java uses camel-case which would make gravity_input gravityInput.
Your problem is one of scope. The gravity_input is declared inside of a constructor or method. To be visible outside of these blocks, it should be declared in the class similar to how you declare the n_bb field.
Your variable gravity_input should be declared as an instance variable (outside the constructor), for it to be later accessed.
The way you're defining it, the name (not the text field) gravity_input dies as soon as the constructor code terminates (reaches closing brace }).
pass parameters as follows into constructor of DataAction:
class DataAction implements ActionListener {
final JTextField textField;
final BallInBox bb;
public DataAction(final JTextField textField, final BallInBox bb) {
this.textField = textField;
this.bb = bb;
}
public void actionPerformed(ActionEvent e) {
String gravityIn = textField.getText();
//System.out.println(gravityIn);
bb.setData(true);
}
}
and use it like this:
gveButton.addActionListener(new DataAction(gravity_input, n_bb));
Then refactor your other actions in a similar way.
The problem is, that your class DataAction doesn't know about your gravity_input textfield.
The textfield gravity_input is only visible to the class BBPanel. To make it visible to the class DataAction, you have to pass the textfield to that class like this:
class DataAction implements ActionListener {
private JTextField gravity_input;
public DataAction(JTextField txtField) {
gravity_input = txtField;
}
public void actionPerformed(ActionEvent e) {
String gravityIn = gravity_input.getText();
//System.out.println(gravityIn);
n_bb.setData(true);
}
}
and change your BBPanel constructor to this:
BBPanel() {
//... omitted
gveButton.addActionListener(new DataAction(gravity_input));
//... omitted
}

Categories

Resources