I want my button to run a whole new class that will do different things inside. I don't know if that is even possible cause i'm really bad at java. My code looks like this at the moment:
public class MainMenu {
private class GardenActivities {
public GardenActivities() {
JFrame GardenAct = new JFrame();
GardenAct.setSize(400, 400);
GardenAct.setVisible(true);
}
}
public static void main(String[] args) {
JFrame choice = new JFrame();
choice.setSize(700, 500);
choice.setLocationRelativeTo(null);
choice.setTitle("Seeds");
choice.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(0, 1));
JButton Labora = new JButton();
Labora.setText("Laboratory");
Labora.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ev) {
GardenActivities();
}
});
JButton Garden = new JButton();
Garden.setText("Garden");
Garden.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ev) {
}
});
choice.getContentPane().add(panel);
ButtonGroup group = new ButtonGroup();
group.add(Garden);
group.add(Labora);
panel.add(Garden);
panel.add(Labora);
choice.setVisible(true);
}
}
Just like I said. I need something to run my GardenActivities class just by pressing Garden button.
Your code doesn't compile, does it? When that happens, you need to post compilation errors with your question so that we can help you with them.
You need to add the key word new before the GardenActivities() statement.
#Override
public void actionPerformed(ActionEvent ev) {
new GardenActivities(); // here
}
Also, put the GardenActivities in its own file. There's no reason for making it a private inner class and many reasons not to do this.
Having said this, I recommend against having one JFrame create and display another JFrame since an application should have usually only one JFrame. Instead consider swapping JPanel "views" using a CardLayout, or if you must show a different window, consider showing the second dependent window as a modal or non-modal dialog.
Also more unsolicited advice: Your main method is doing way too much. Most of the code inside of the static main method should go inside the non-static main gui class, whatever that is, perhaps in its constructor or in an initGui() method that the constructor calls. The main method should just create an instance of the main gui class, make it visible, and that's about it.
And regarding:
I don't know if that is even possible cause i'm really bad at java.
Keep writing lots and lots of code, a ton of code, and keep reviewing tutorials and textbooks, and this will change.
I think that you just need to add:
new GardenActivities();
Into your JButton's actionPerformed() method.
Good Luck!
One way to do what you want, we make the GardenActivities class implement ActionListener itself.
Then your code would look something like this:
Garden.addActionListener(new GardenActivities());
Otherwise, your plan should work.
NOTE
See comments for opposing opinions about why one would want to leave the ActionListener in the anonymouse inner class and have it call into GardenActivities.
Thank you #HovercraftFullOfEels
As others have pointed out, this:
#Override
public void actionPerformed(ActionEvent ev)
{
GardenActivities();
}
Should look like:
#Override
public void actionPerformed(ActionEvent ev)
{
new GardenActivities();
}
There is no reason to create an inner class, and GardenActivities can be, and should be, its own class.
Related
I understand how to create a button and it's application in Java. Would anyone be able to show me the code to be able to make the button in the code below be able to print something as simple as hello world in the terminal. I am using bluej if that is of any matter. I am very sorry I am a beginner coder.
JButton button = new JButton();
button.setActionListener(e -> System.out.println("Clicked"));
This uses a lambda expression. Inside it, you can add as much code as you like, but add it between {} if it's more than a line.
More on buttons here
You need a listener for your button.
JButton button= new JButton("Button");
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
System.out.println("Hello World");
}
});
the button will 'listen' for the action and preform whatever task you define for it.
ActionListener is what you are looking for. There is a very nice guide on Oracle's website. You should look into this tutorial and understand different ways of creating ActionListeners. I will give you a simple example which doesn't involve Anonymous Classes because I am not sure of how much you know about them.
public class Frame extends JFrame implements ActionListener {
public Frame() {
super("Test"); // calling the superclass
setLayout(new FlowLayout()); // creating a layout for the frame
setDefaultCloseOperation(EXIT_ON_CLOSE);
// create the button
JButton jbTest = new JButton("Click me!");
/* 'this' refers to the instance of the class
because your class implements ActionListener
and you defined what to do in case a button gets pressed (see actionPerformed)
you can add it to the button
*/
jbTest.addActionListener(this);
add(jbTest);
pack();
}
// When a component gets clicked, do the following
#Override
public void actionPerformed(ActionEvent ae) {
System.out.println("Hello!");
}
}
private JButton jBtnDrawCircle = new JButton("Circle");
private JButton jBtnDrawSquare = new JButton("Square");
private JButton jBtnDrawTriangle = new JButton("Triangle");
private JButton jBtnSelection = new JButton("Selection");
How do I add action listeners to these buttons, so that from a main method I can call actionperformed on them, so when they are clicked I can call them in my program?
Two ways:
1. Implement ActionListener in your class, then use jBtnSelection.addActionListener(this); Later, you'll have to define a menthod, public void actionPerformed(ActionEvent e). However, doing this for multiple buttons can be confusing, because the actionPerformed method will have to check the source of each event (e.getSource()) to see which button it came from.
2. Use anonymous inner classes:
jBtnSelection.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
selectionButtonPressed();
}
} );
Later, you'll have to define selectionButtonPressed().
This works better when you have multiple buttons, because your calls to individual methods for handling the actions are right next to the definition of the button.
2, Updated. Since Java 8 introduced lambda expressions, you can say essentially the same thing as #2 but use fewer characters:
jBtnSelection.addActionListener(e -> selectionButtonPressed());
In this case, e is the ActionEvent. This works because the ActionListener interface has only one method, actionPerformed(ActionEvent e).
The second method also allows you to call the selectionButtonPressed method directly. In this case, you could call selectionButtonPressed() if some other action happens, too - like, when a timer goes off or something (but in this case, your method would be named something different, maybe selectionChanged()).
Your best bet is to review the Java Swing tutorials, specifically the tutorial on Buttons.
The short code snippet is:
jBtnDrawCircle.addActionListener( /*class that implements ActionListener*/ );
I don't know if this works but I made the variable names
public abstract class beep implements ActionListener {
public static void main(String[] args) {
JFrame f = new JFrame("beeper");
JButton button = new JButton("Beep me");
f.setVisible(true);
f.setSize(300, 200);
f.add(button);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Insert code here
}
});
}
}
To add an action listener, you just call addActionListener from Abstract Button.
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.
First off, I'm new to Java, so please be gentle.
I have a JFrame which has two 'JPanels', one of which is a separate class (i've extended the JPanel). Ideally I'd like to 'dispatch and event' or notify the other JPanel object on the JFrame.
I have an array of JButtons in the custom JPanel class, which i'd like to add an event listener to. Upon clicking the JButton, i'd like to change something on the other JPanel.
I'm really not sure how to do this, so I moved the event handler into the JFrame class, and tried to do the following:
panel.buttonArray[i][j].addActionListener(this);
However, doing that didn't work at all. Annoyingly, Eclipse didn't complain either...
Any tips on how I can achieve this?
This was horribly explained, sorry.
Think of this not in terms of panels but in terms of objects. As long an object, lets say it has a name of object77, has a reference to the other object, call it object42, object77 can call methods on object42.
object77.methodInObject42();
panel77.methodInPanel42();
As for the event handler, then
buttonOnPanelXX.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
panel77.methodInPanel42();
}});
or even better...
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable(){
public void run() {
panel77.methodInPanel42();
}});
}});
G'day all,
I am coding a main menu for a project. The menu displays properly. I have also set up ActionListeners for the three buttons on the menu.
What I wish to do is reuse the JPanel for a new set of radio buttons when the user chooses "Start a New Game".
However, coding ActionPerformed to remove the existing components from the JPanel has me stumped. I know removeAll is somehow important, but unfortunately NetBeans informs me I cannot call it on my mainMenu JPanel object within ActionPerformed. So i have commented it out in my code below, but left it in so you can see what I am trying to do.
Your thoughts or hints are appreciated.
Here is my main code:
public class Main {
public static void main(String[] args) {
MainMenu menu = new MainMenu();
menu.pack();
menu.setVisible(true);
}
}
Here is my mainMenu code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MainMenu extends JFrame implements ActionListener {
JButton startNewGame = new JButton("Start a New Game");
JButton loadOldGame = new JButton("Load an Old Game");
JButton seeInstructions = new JButton("Instructions");
public MainMenu() {
super("RPG Main Menu");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel mainMenu = new JPanel();
mainMenu.setLayout(new FlowLayout());
startNewGame.setMnemonic('n');
loadOldGame.setMnemonic('l');
seeInstructions.setMnemonic('i');
startNewGame.addActionListener(this);
loadOldGame.addActionListener(this);
seeInstructions.addActionListener(this);
mainMenu.add(startNewGame);
mainMenu.add(loadOldGame);
mainMenu.add(seeInstructions);
setContentPane(mainMenu);
}
public void actionPerformed(ActionEvent evt) {
Object source = evt.getSource();
if (source == startNewGame) {
// StartNewGame code goes here
// mainMenu.removeAll();
}
if (source == loadOldGame) {
// LoadOldGame code goes here
}
if (source == seeInstructions) {
// Quit code goes here
}
}
}
Consider using a CardLayout instead, which manages two or more components (usually JPanel instances) that share the same display space. That way you don't have to fiddle with adding and removing components at runtime.
You need mainMenu to be a member variable:
public class MainMenu extends JFrame implements ActionListener {
JButton startNewGame = new JButton("Start a New Game");
JButton loadOldGame = new JButton("Load an Old Game");
JButton seeInstructions = new JButton("Instructions");
JPanel mainMenu = new JPanel();
Why do you feel the need to re-use this object?
You don't have a reference to mainMenu actionPerformed use. If you declare mainMenu with the buttons. It would work.
The problem is that the actionPerformed method is trying to call the JPanel mainMenu which is out of scope, i.e. the mainMenu variable is not visible from the actionPerformed method.
One way to get around this is to have the JPanel mainMenu declaration in the class itself and make it an instance field which is accessible to all instance methods of the class.
For example:
public class MainMenu extends JFrame implements ActionListener
{
...
JPanel mainMenu;
public MainMenu()
{
...
mainMenu = new JPanel();
...
}
public void actionPerformed(ActionEvent e)
{
...
mainMenu.removeAll();
}
}
Avoid attempting to "reuse" stuff. Computers are quite capable of tidying up. Concentrate on making you code clear.
So instead of attempting to tidy up the panel, simply replace it with a new one.
Generally a better way to write listeners is as anonymous inner classes. Code within these will have access to final variables in the enclosing scope and to members of the enclosing class. So, if you make mainMenu final and you ActionListeners anonymous inner classes, your code should at least compile.
Also don't attempt to "reuse" classes. Try to make each class do one sensible thing, and avoid inheritance (of implementation). There is almost never any need to extend JFrame, so don't do that. Create an ActionListener for each action, rather than attempting to determine the event source.
Also note, you should always use Swing components on the AWT Event Dispatch Thread. Change the main method to add boilerplate something like:
public static void main(final String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() { public void run() {
runEDT();
}});
}