Java Simple ActionListener Questions - java

I have a main class in a program that launches another class that handles all the GUI stuff.
In the GUI, i have a button that i need to attach an ActionListener to.
The only problem is, the code to be executed needs to reside within the main class.
How can i get the ActionPerformed() method to execute in the main class when a button is clicked elsewhere?

Make your controller ("main" class) implement the ActionListener interface, then pass a reference to the view class:
public class View extends JFrame {
public View(final ActionListener listener) {
JButton button = new JButton("click me");
button.addActionListener(listener);
button.setActionCommand("do_stuff");
getContentPane().add(button);
pack();
setVisible(true);
}
}
public class Control implements ActionListener {
public Control() {
new View(this);
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("do_stuff")) {
// respond to button click
}
}
}
It can also be done with Actions, but that's more useful where you want one piece of code to respond to many buttons.

Implement an anonymous inner class as ActionListener on the button, then call the method on your main class. This creates less dependencies and avoids the tag & switch style programming that implementing the ActionListener interface on a main class tends to promote.
In either case it will create a cycle in your dependency graph: the main class will know about the button and the button will need to call the main class. This might not be a good idea since it will make it hard to compose things in any other way. But without further information it is hard to judge the situation or recommend anything concrete.

Implement ActionListener in your main class and add the main class instance as a listener on your GUI button.

Related

How to close a JFrame on a class that implements ActionListener

I need to close a specific JFrame with another class that implements ActionListener
public class EditStudent extends JFrame {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
EditStudent frame = new EditStudent();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}
I will use this class to a JButton on that JFrame. (It's like a controller to a JButton)
public class EditFileController implements ActionListener {
#SuppressWarnings("unused")
private JButton btnEdit = new JButton();
public EditFileController(JButton btnEdit) {
super();
EditStudent.btnEdit = btnEdit;
}
}
Every searchable method. I've been searching for at least 5 hrs.
Well start with the basics of how to write an ActionListener. The code you posted doesn't even implement the actionPerformed(...) method so it won't even compile.
Read the Swing tutorial for Swing basics. Maybe start with the section on How to Use Lists. The ListDemo code shows how to use an inner class to define an ActionListener.
Your controller class makes no sense to me. You appear to be making it to complicated. For example why would you pass the button as a parameter but also make a new instance of the button in the class.
An ActionListener does NOT to define the button or have it passed as a parameter.
All you need to do is create the button where you add all other components to the frame. Then you add the ActionListener to your button.
Then the the basic code in your ActionListener would be:
Window window = SwingUtilities.windowForComponent(event.getSource());
window.dispose();
Once you get that working and understand the basic concepts you may want to check out Closing an Application which presents a simple API to create reusable code that can be used for any frame.

Can you make a jButton in a jFrame generate its code into another class?

Can you make a button in a jframe generate its Events>Action>actionPerformed code into another class besides the jframe class. If you cant, can you manually make the code in the different class to make the button do something.
Yes, you can.
Basically, you use myJbutton.setActionListener(new MyButtonActionListener()).
And you have a class MyButtonActionListener implements ActionListener. The method actionPerformed will be called automatically.
EDIT: Added code below
public class MyButtonActionListener implements ActionListener {
#Override
public void actionPerformed(EventListener e){
// Do stuff
}
}
And you setup your button:
JButton myButton = new JButton("mybutton");
myButton.setActionListener(new MyButtonActionListener());

Storing JFrame output into a String in the Main Program

It seems to me that so far, everything that happens within JFrame stays within JFrame. (Probably should have gotten into JavaFX instead of Swing)
Let's say you have a JFrame Class (gui_frame) that utilizes JButtons with a nested class named HandlerClass that implements ActionListener, as shown below:
public class gui_frame extends JFrame {
private JButton button1;
public gui_frame() {
super("Title");
setLayout(new FlowLayout());
button1 = new JButton("Hello");
add(button1);
HandlerClass handler = new HandlerClass();
button1.addActionListener(handler);
}
private class HandlerClass implements ActionListener{
public void actionPerformed(ActionEvent e){
//insert code here
}
}
}
And then you have the main code, which calls upon this gui_frame class.
public class main {
public static void main(String[] args){
//insert some unrelated code here
gui_frame gf = new gui_frame();
gf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gf.setSize(400,75);
gf.setVisible(true);
String button_name;
//insert some code that uses button_name
}
}
Essentially, I'm trying to store the name of the button in the JFrame class gui_frame (in this case "Hello"), AFTER BEING CLICKED, into the String button_name in the main class, during run time.
Is this possible? What do I have to insert into the actionPerformed method in the gui_frame, in order to make this happen?
There's a few ways that you could do this:
implement the ActionListener as a lambda in the main class (btw, that should be capitalized, i.e. "Main"), and pass the lambda to the gui_frame class (again, that should be "GuiFrame"), and have the GuiFrame class apply the listener to the button
create an interface for the GuiFrame class to use to notify the Main class that the button has been clicked (and the name of the button). Have the Main class implement that interface, and then pass the instance of Main to the GuiFrame class. Then have the GuiFrame's ActionListener call the method in the Main class' interface to notify it.
Store the name of the last clicked button in the GuiFrame class, and have the Main class ask for it when it needs it (if it doesn't need to know when the button is clicked).

Closing JFrame with a JButton

Im having problem with this code , it doesn't compile . Could you help me ?
I need to close the JFrame when i click the button
public class SlotMachine extends JFrame
{
/*
*
*/
JButton btnExit = new JButton("Exit");
btnExit.addMouseListener(new MouseAdapter()
{
#Override
public void mouseClicked(MouseEvent arg0)
{
this.dispose();
}
});
}
The error is = The method dispose() is undefined for the type new MouseAdapter(){}
I dont know how to get the SlotMachine object from the mouseClicked method
You're calling this.dispose(); the key here being that this refers to the inner class, the MouseListener, and MouseListener doesn't have a dispose() method.
Solution: get rid of this, and it should work, since the compiler will then look into the outer class if the inner class does not contain the method. Alternatively you could specify which this you mean: SlotMachine.this.dispose(); will tell the compiler to call the method of the outer SlotMachine class.
Use an ActionListener on a JButton for several reasons:
Default behavior of buttons is to be activated by spacebar press if the button has focus. This will not work for a MouseListener.
Also an expected behavior is that if the button is disabled via setEnabled(false), then pressing it should not cause the action to be fired. This does not work with MouseListener but does with ActionListener.
You can easily share the ActionListener (or better yet, an AbstractAction) with other components including JMenuItems.

Passing "this" as a Method Argument - Clarification

I am currently working on Java Swing lessons after finishing my first set of lessons in Java. In this lesson, we are working on communication between different components (buttons,toolbars,etc.) that we have been studying. The problem is, "this" is being passed as a method argument for the addActionListener() method. This works, however, I do not completely understand what it is doing. I did some research regarding "this," and found that the most popular usage for the "this" keyword would be in constructors with variables of the same names. I could not find an example that would fit my case. By looking at the code below, I will explain that parts of the code that I understand.
import java.awt.FlowLayout; Implements FlowLayout class
import java.awt.event.ActionEvent; //Imports ActionEvent Class
import java.awt.event.ActionListener; //Imports ActionListener Interface
import javax.swing.JButton; //Imports JButton class
import javax.swing.JPanel; //Imports JPanel class
public class Toolbar extends JPanel implements ActionListener {
// ^ Inherits JPanel & Implements ActionListener Interface
private JButton helloButton; //Creating variable of JButton type
private JButton goodbyeButton; //Creating variable of JButton type
public Toolbar() { //Constructor
helloButton = new JButton("Hello"); //Creates new JButton
goodbyeButton = new JButton("Goodbye"); //Creates new JButton
helloButton.addActionListener(this); //Question 1
goodbyeButton.addActionListener(this); //Question 1
setLayout(new FlowLayout(FlowLayout.LEFT)); //Sets Layout Type to Left
add(helloButton); //Adds button to FlowLayout (Layout Manager) Interface
add(goodbyeButton); //Adds button to FlowLayout (Layout Manager) Interface
}
public void setTextPanel(TextPanel textPanel) {
//No Usage Yet!
}
public void actionPerformed(ActionEvent arg0) { //Unimplemented Method from ActionListener
System.out.println("A button was clicked"); //Prints after button is clicked.
}
}
Question 1: As you can see, after creating two JButtons, we are adding an addActionListener() method in order to see detect if the button has been clicked. If it has been clicked, then it will do any code typed in actionPerformed that is implemented from the ActionListener interface. In previous lessons, we had a different way of making a button respond to a click. It did the same thing, but it looked like this:
btn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
textPanel.appendText("Hello\n");
}
});
In this example, rather than printing to the console to test to see if the actionListener() worked, we just appended the text to a text area from a customized component. In the code directly above this text, we are working with an anonymous class.
So... The question is, what exactly is "this" doing as it is being passed as a method argument in addActionListener()? I know that it is printing "A button was clicked" to the console, but I don't understand the logic behind what "this" is doing to send that the button has been clicked to actionPerformed().
This is what the applications looks like:
This is the application in motion, and the buttons have already printed to the console after being clicked. I thought it might give you a better idea of what I am working on. I hope somebody can shed some light on this, and explain how "this" is working in this context. Thank you!
this represents the current instance of your class.
Toolbar class implements ActionListener interface, that means it provides an implementation of method actionPerformed.
So, helloButton.addActionListener(this); becomes possible (try to remove implements ActionListener from class declaration, the code won't compile).
Saying this, Toolbar instances can be considered as ActionListener objects and can be passed to button.addActionListener.
When using
btn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
}
}
you create a new implementation of the ActionListener interface in the fly. This kind of implementation is named anonymous.
The both solutions are valid. Prefer the anonymous solution if the code in actionPerformed cannot be used from another place.
this is just an instance of your Toolbar class. It is used inside instance methods to represent the current instance. Essentially you can imagine your class has another private member variable named this, that points to a Toolbar object.
Since Toolbar implements ActionListener you are assigning the newly instantiated Toolbar object as a listener to the buttons (meaning the Toolbar.actionPerformed() method will be called when the buttons are clicked.)
By implementing ActionListener and then passing this to addActionListener method you are asking to be informed of any actions that are performed through a call to your actionPerformed method.
Or, more simply, you are giving the button your phone number and asking it to call you whenever something happens.
In the earlier lessons you were stating what should happen - print this text or add some text to the textPanel. To do this you were making an ActionListener on-the-fly. Now you implement ActionListener yourself you can request a callback to you anstead of making a listener one on-the-fly.
The addActionListener method for a swing component takes an argument of type ActionListener. A class that implements an ActionListener contains code that specifies what should be done when someone interacts with a swing component.
When you pass this to the addActionListener method, you are passing a reference to the current object that is being instantiated. As it happens, the current object being instantiated is also an ActionListener (as it implements ActionListener) and can therefore be passsed to the addActionListener method.
When you interact with the JButton in the GUI, the actionPerformed method of Toolbar class will be called since that is the ActionListener that you registered the JButton with.
These two examples would do the same thing (assuming all imports are there, and that capitalization would be correct):
public static void main(String args[]){
myFrame frame = new myFrame();
myFrame.addActionListener(new myListener);
}
public myFrame extends JFrame{
public myFrame(){
super("myFrame");
}
}
public myListener implements ActionListener{
public void ActionPerformed(ActionEvent e){
//Do Stuff
}
}
and
public static void main(String args[]){
myFrame frame = new myFrame();
}
public myFrame extends JFrame implements ActionListener{
public myFrame(){
super("myFrame");
this.add(this);
}
public void ActionPerformed(ActionEvent e){
//Do Stuff
}
}
The advantage of having the ActionListener be this is that it would have more direct access to fields and methods, if you want to make the modifier on the methods private.
However, if you want to avoid if/else if monstrosities for handling multiple buttons, I recommend either using a separate ActionListener(and providing a means to change what needs to be changed), or taking a look at anonymous classes and lambda expressions.
Often with object-oriented coding, it's worth role-playing the part of an object of the class you're coding. If you do that, "this" means "me".
And because Java is pass-by-reference, "this" is an arrow pointing to "me".
public class Foo implements ActionListener {
public void actionPerformed(ActionEvent e) {
// do something useful with e
}
}
Here we've written a class Foo. Since we've said it implements ActionListener, it must have an actionPerformed() method. Anything can call that:
ActionListener listener = new Foo(...);
ActionEvent event = ...;
foo.actionPerformed(event);
And we can create a Foo and give it to something that generates events:
ActionListener listener = new Foo(...);
button.addListener(listener);
If we role-play the object, you can think of this last line as "Hey button! Tell listener whenever an action happens.".
Now, what if we want the listener to take control of who tells it what on its own? "Hey button, tell me whenever an action happens".
public class Foo implements ActionListener {
public attachToButton(JButton button) {
button.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
// do something useful with e
}
}
It may help to imagine what the button's addActionListener code might look like:
public class JButton { // not the real JButton code, but it will be similar
private List<ActionListener> actionListeners = new ArrayList<ActionListener>();
public void addActionListener(ActionListener a) {
actionListeners.add(a);
}
// called internally when an event happens
private void onEvent(ActionEvent e) {
for(ActionListener listener : actionListeners) {
listener.actionPerformed(e);
}
}
}
So, if you're the listener that called addActionListener(this), then that List contains a reference that points right back at you, which the button uses to tap you on the shoulder every time an action occurs.

Categories

Resources