How to add actions to a button in java - java

I have been working with java buttons, and I have created a button ,but when i click the button, I want the shape of the object to change. This is the code I've worked on
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class shapes {
public static void main(String[] a) {
JFrame f = new JFrame("Change shapes");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton b = new JButton("Shapes Change");
f.getContentPane().add(b);
f.pack();
f.setVisible(true);
}
Public void paint (Graphics g)
{
//no clue what to do here
}
private static abstract class MyButton extends JButton implements ActionListener {
MyButton()
{
addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == b)
{
//no clue what to do here
}
}
}
}
At first, There is a shape created, once the button is clicked it I want to change it to another shape.

There really should be any need to subclass JButton. If you want to customise the button, you could use the Action API instead, see How to Use Actions.
To perform custom painting your should extend a Swing component like JComponent or JPanel and override the paintComponent method...
See Performing Custom Painting for more details.
You would then need to provide some method which you could call to tell the component that the shape should change to how the shape should be changed.
You would then provide a means for your buttons ActionListener to reference the instance of the paint panel and call these methods...

You simply add an ActionListener to the button:
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// do some action
}
});
A couple other things to note:
You should not run Swing methods outside the Event Dispatch Thread (EDT) or you may run into unpredictable errors.
Java naming conventions specify that class names should be capitalized. In your code, you named the class "shapes" but it is more proper to name it "Shapes".

First declare and define methods for drawing objects. For example drawSquare (), drawCircle () which draws required shapes. Define radio button or something similar to that to get the users choice (to know which object has to be drawn) . In actionPerformed () check which radiobutton is selected and call the appropriate method for drawing objects and call the repaint () for updating in user interface

Related

ActionListener interface

public class myWindow extends JFrame implements ActionListener{
if i have this code my class will be a JFrame where where I can add component and add actionlistener to them in my constructor as followed
public MyWindow()
{
JButton b = new Jbutton("button");
b.addActionListener(this);
}
this keyword will work as an anonymous actionlistener object(which is my class) right ?
later on i will override the actionPerformed method with the heading:-
public void ActionPerformed(ActionEvent ae)
{ :
:
}
I really have a big confusion here .. my book says "the listener object invokes an event handler method with the event as an argument "
listener object : this
event handler method :ActionPerformed(ActionEvent ae)
argument: my event is the JButton b .. how come when it's not of EventAction type ? And if so why we are using :
ae.getActionCommand();
I thought it's a method to tell which component fired the event,why we need it when the component is passed as an argument then?
this keyword will work as an anonymous actionlistener object(which is my class) right ?
No this will be an Object of class which is implementing the actionsListener. In your case it is "MyWindow".
my event is the JButton b .. how come when it's not of EventAction type ? And if so why we are using :
JButton b is a component not an event. Events describes the changed in state of the source. When users interact with GUI, events are generated like clicking of button, moving the mouse.
Reference from Click here
Event Handling is a mechanism that controls the event and decides what should happen if an event occurs.
Steps involved in event handling:-
The User clicks the button and the event is generated.
Now the object of concerned event class is created automatically and information about the source and the event get populated with in same object.
Event object is forwarded to the method of registered listener class.
the method is now get executed and returns.
I thought it's a method to tell which component fired the event,why we need it when the component is passed as an argument then?
Now you would have understood that there could be many buttons registered to the same ActionsListerner. Now to perform different actions for different events,
e.getActionCommand() comes handy, it will tell you which button is the source of firing the event.
Hope this helps.
I have tried to give you can example of a simple JButton program.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ButtonSwing {
private int numClicks = 0;
public Component createComponents() {
//Method for creating the GUI componenets
final JLabel label = new JLabel("Clicks: " + "0"); //final so that i can access inside inner class
JButton button = new JButton("Simple Button");
button.addActionListener(
//inner class for ActionListener. This is how generally it is done.
new ActionListener() {
public void actionPerformed(ActionEvent e) {
numClicks++;
label.setText("Clicks: " + numClicks);
System.out.println(e.getActionCommand());
System.out.println(e.getModifiers());
System.out.println(e.paramString());
}
}
);
JPanel pane = new JPanel(); //using JPanel as conatiner first.
pane.setLayout(new FlowLayout());
pane.add(button); // adding button to the JPanel.
pane.add(label); // adding label to the JPanel.
return pane;
}
public static void main(String[] args) {
JFrame frame = new JFrame("SwingApplication");
ButtonSwing obj = new ButtonSwing();
Component contents = obj.createComponents();
frame.getContentPane().add(contents);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.pack(); //It will cause the window to be sized to fit the preferred size
//and layouts of its subcomponents.
frame.setVisible(true);
}
}
Your JButton is a component not an event. Events are generated by some action on components in this case When you click your button, an ActionEvent will be fired and it will be passed to all the listeners who subscribed to that event in this case it is your MyWindow object which is serving as an ActionListener

for ComboBox, addActionListener -> actionPerformed?

if I have
ComboBox box = b;
b.addActionListener(this);
shouldn't I expect this.actionPerformed(event) to be called
when the combobox is operated?
I have a test frame with a few combo boxes, which seem to operate
normally, but no actionPerformed is ever called. Perhaps the frame
itself needs to be armed in some way?
Your question is not so clear and you didn't give it a proper title.
If you want to add ActionListener to a ComboBox, this is how you do it:
ComboBox box = new ComboBox();
box.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
}
});
From what I understand you just want to create a ComboBox from within a class that with be handling the action events. To do so I would suggest that the class inherits from ActionListener and override (use the #Override tag) the actionPerformed. Just Overriding the action perform is not enough if the class is not inheriting from ActionListener.
public class MyListener extends ActionListener {
#Override
public void actionPerformed (ActionEvent evt){
//code you want to execute when the event happens
}
public void methodCreatingComboBox(){
ComboBox b = new ComboBox();
b.addActionListener(this);
//other stuffs
}
}
that would work like a charm ! And you can use that same instance of MyListener for multiple events.
Here's the correct answer. I was using com.codename1.ui.Dialog as
the top level window. I switched to using com.codename1.ui.Form
and now the actions are firing as expected.
Something in the environment constructed by Dialog (which extends Form)
is interfering with the event mechanism. Perhaps by design.

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.

Some doubts about the use of adapter and listener in Java Swing

I am studying Java Swing and the Adapters to handle events but I have some doubts related to the following working example that I am studying:
import java.awt.*;
import java.awt.event.*;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.TitledBorder;
public class ListenerDemo extends JPanel implements MouseMotionListener{
// Label che visualizzano la posizione X ed Y del cursore:
JLabel labelX;
JLabel labelY;
public ListenerDemo() {
/* Add a MouseMotionListener to this object to catch when the user uses the mouse: */
addMouseMotionListener(this);
Font f = new Font(Font.SANS_SERIF, Font.PLAIN, 50);
TitledBorder borderX = new TitledBorder("Mouse X");
TitledBorder borderY = new TitledBorder("Mouse Y");
borderX.setTitleJustification(TitledBorder.CENTER);
borderY.setTitleJustification(TitledBorder.CENTER);
labelX = new JLabel("0");
labelX.setBorder(borderX);
labelY = new JLabel("0");
labelY.setBorder(borderY);
labelX.setFont(f);
labelY.setFont(f);
super.add(labelX);
super.add(labelY);
}
// NOT IMPLEMENTED:
public void mouseDragged(MouseEvent e) {}
// IMPLEMENTED:
public void mouseMoved(MouseEvent e) {
labelX.setText("X : "+e.getX());
labelY.setText("Y : "+e.getY());
}
public static void main(String [] argv) {
// WindowsAdapter che implementa solo il metodo WindowClosing()
WindowAdapter adpt = new WindowAdapter() {
/*
* Alla chiusura della finestra ripassa il focus al frame principale.
* #param A low-level event that indicates that a window has changed its status
*/
public void windowClosing(WindowEvent e) {
System.exit(0);
}
};
JFrame frame = new JFrame("ListenerDemo"); // Frame esterno
// Add at the frame ONLY the anonymous adapter WindowAdapter class:
frame.addWindowListener(adpt);
// Add to the ContentPane inside the frame the ListenerDemo listener:
frame.getContentPane().add(new ListenerDemo(), null);
// Display the window:
frame.pack();
frame.setVisible(true);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
}
}
I have some difficulties to understand the logic of this program:
The first doubt is Why the **ListenerDemo class extendes JPanel and implements MouseMotionListener?
I think that the logic of the program is the following one:
Inside the main() method I create a new WindowAdapter object that is an instance of the WindowAdapter that allows me to implement only some methods that handle events related to my WindowEvent events. So, using this adapter, I can avoid implementing some listener methods that do not interest me. In this case the WindowAdapter implement only the moethod related to the closoure of a window and not implement others windows events.
Is this reasoning correct?
Following the example shows the difference with the concept of using the classic listener in which I have to implement all the method that handle all the events related to a specific listener.
In this example, in my main(), I add a custom ListenerDemo to the content of the frame and I think that this listener add a addMouseMotionListener to the current object by this line:
addMouseMotionListener(this);
So I have a listener that catch all the events related to the use of the mouse in the content of my frame.
In this case, because I am using listener, I have to implement both the methods of the MouseMotionListener listener: addMouseMotionListener and removeMouseMotionListener
Is it correct?
I have another doubt: it seems to me that this coding style is pretti orrible (but maybe it is only my impression because I don't know it) because it do all in a single class, can I separate it in a better way?
Tnx
Andrea
Your ListenerDemo is a graphical user interface, so that's why it extends JPanel: that way it inherits all graphical properties of a default panel.
In my opinion, it is bad practice that ListenerDemo also implements MouseMotionListener. It is a misuse of the adapter pattern. So what is that pattern?
In short: in ListenerDemo you have some code:
labelX.setText("X : "+e.getX());
labelY.setText("Y : "+e.getY());
which you want to wire to an event of the panel: when the mouse is moved.
The typical adapter pattern uses an anonymous inner class for this:
public ListenerDemo() {
addMouseMotionListener(new MouseMotionListener() {
// NOT IMPLEMENTED:
public void mouseDragged(MouseEvent e) {}
// IMPLEMENTED:
public void mouseMoved(MouseEvent e) {
labelX.setText("X : "+e.getX());
labelY.setText("Y : "+e.getY());
}
});
// remaining code
}
The effect is the very same, but in my opinion it is awkward to make ListenerDemo implement MouseMotionListener. No other external class needs to know that your demo can capture mouse events, so it should be hidden in its implementation.
The *Adapter classes are just helpful stubs that provide empty implementations for every method of the implementing interface. You can use them, if you do not want to implement all methods - like in your example where you're only interested in the window-closing event.
It is a very common practice that the class that realizes your UI also implements the event handler interface(s). That's mainly because it's convenient, but in fact it's bad style! Your ListenerDemo needs the listener only internally, so it is not a good idea to add it to the public API of the class. (You don't want users of your class to use it somewhere as a MouseMotionListener, do you?)
So it's much better to have a anonymous inner class that either implements MouseMotionListener or derives from MouseAdapter:
private final MouseMotionListener mouseListener = new MouseAdapter() {
public void mouseMoved(MouseEvent e) {
labelX.setText("X : "+e.getX());
labelY.setText("Y : "+e.getY());
}
}
Now, in the constructor you can register mouseListener instead of this.
Concerning your question about separation: You should/could move the main method out into a separate 'Main' class.

How to propogate Swing events from a inner component to a container?

I created a component based on a JPanel that contains a textfield and a checkbox. Since I use it as component and put it around in other panels I'd like to be able to set a KeyPressed event for the panel. Obiouvsly this doesn't work as the keyPressed events fire for the inner textfield. Is it there a way to propagate them to the JPanel as it was receiving them instead of the textfield? I tried with handleEvent but it doesn't even compile.
Let's clarify the question. I created this big element containing a textfield. Now a want to use this element in another and I want to set the OTHER ONE as the listener. So there is the JPanel between. That's the problem.
You can use javax.swing.event.EventListenerList in the JPanel containing the JTextField, and create a addKeyListener public method.
import javax.swing.event.EventListenerList;
public static class TestPanel extends JPanel implements KeyListener{
private JTextField text;
private EventListenerList listenerList = new EventListenerList();
TestPanel(){
text = new JTextField();
text.addKeyListener(this);
}
public void keyPressed(KeyEvent e){
//doesn't create a new array, used for performance reasons
Object[] listeners = listenerList.getListenerList();
//Array of pairs listeners[i] is Class, listeners[i + 1] is EventListener
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == KeyListener.class) {
((KeyListener)listeners[i+1]).keyPressed(e);
}
}
}
public void addKeyListener(KeyListener l) {
listenerList.add(KeyListener.class, l);
}
public void keyReleased(KeyEvent e){
//idem as for keyPressed
}
public void keyTyped(KeyEvent e){
//idem as for keyPressed
}
}
Try adding an ActionListener to the JPanel. The actionPerformed() method in the ActionListener will get called when the user presses key in the JTextfield. You can call getSource() on the event object to determine if the event was fired due to action in JTextField and act accordingly.
you could add the JPanel derivative to the JTextField as an event listener.
You will need to do some plumbing to get this to work, for example making your JPanel derivative implement KeyListener and implementing the required methods.

Categories

Resources