Action Listener, Determing which button was pressed

B

Ben

Hi,
Could anyone help me with this problem. I have an action listener
associated with a number of buttons. I can get the action listener to
work, but what code do I need to findout which button was pressed.

This is the layout of the action listener class.

import java.awt.event.*;
import java.awt.Component;

public class ButtonListener implements ActionListener
{
public void actionPerformed (ActionEvent e)
{

}

}

Thanks in advance.

Ben.
 
C

Chris Lamb

Hi,
Could anyone help me with this problem. I have an action listener
associated with a number of buttons. I can get the action listener to
work, but what code do I need to findout which button was pressed.

This is the layout of the action listener class.

import java.awt.event.*;
import java.awt.Component;

public class ButtonListener implements ActionListener
{
public void actionPerformed (ActionEvent e)
{

}

}

Thanks in advance.

Ben.

Have you tried setActionCommand() method for the JButton? Then you can use
e.getActionCommand() in your ActionListener to query it.

Chris
 
C

Chris Lamb

Or more directly, use e.getSource().

It's usually better to create a new listener instance for each event source.

Ah, yes indeedy. I'm afraid I must put my hand up and admit to using the
'cheap 'n' nasty' on more occasions than is appropriate :).


Chris
 
T

Thomas Hawtin

Chris said:
Have you tried setActionCommand() method for the JButton? Then you can use
e.getActionCommand() in your ActionListener to query it.

Or more directly, use e.getSource().

It's usually better to create a new listener instance for each event source.

Tom Hawtin
 
K

Knute Johnson

Thomas said:
Or more directly, use e.getSource().

It's usually better to create a new listener instance for each event
source.

Tom Hawtin

I don't know, for one or two buttons maybe. But if you have a bunch of
menus and buttons I find it to be much less confusing to have all of the
events go to the same listener and separate them out there.
 
O

ossie.moore

Here here. Separate listeners for each button in many situations is
stunningly inefficient and confusing.
 
T

Thomas Hawtin

Here here. Separate listeners for each button in many situations is
stunningly inefficient and confusing.

Really?? Are you referring to class loading time? I would be surprised
if that makes any significant difference in this day and age. I'm
confused by the idea that it's confusing.

Tom Hawtin
 
K

Knute Johnson

Thomas said:
Really?? Are you referring to class loading time? I would be surprised
if that makes any significant difference in this day and age. I'm
confused by the idea that it's confusing.

Tom Hawtin

You said better, I said less confusing, I think we both have
preferences. It is my preference to group the event handling together
if I have more than a couple of related events. I usually do that when
I create a frame with a bunch of menus. I like the menu creation code
together and the event processing code together. Less confusing for the
unimaginative like me :).
 
T

Thomas Hawtin

Roedy said:
each anonymous listener class adds about 3K overhead.

3K overhead to what?

Class files each have string references to all packages, method names
and signatures involved, which makes them larger than should be
expected. Within JAR files they will normally be compressed.

I have to confess a good deal of ignorance about runtime structures.
Presumably you don't need all the copies of the same data. That should
strip away most of the inefficiency.

Tom Hawtin
 
T

Thomas Hawtin

Roedy said:
that is how much real ram they consume when they are sitting there
fielding events.

I couldn't believe it. So I consulted the google. And indeed the web
does say 3K. It's even printed on like real paper, so it must be right.

http://java.sun.com/docs/books/performance/1st_edition/html/JPClassLoading.fm.html#24833

Okay, so perhaps it's the old school book trick wherein generations of
authors copying other authors' mistakes. So I shall do my own testing.
Below is a quick & dirty program to create simplistic scalable example
code. And indeed going up to 1000 anonymous inner classes it takes 3K a
class. Unbelievable.

Going higher hit a problem with a laughable hash algorithm in javac. I
patched that with the String code, and reduced my expectations to fit
within the limits of the class file format. 3000 anonymous inner classes
require less memory than just one!!

???

Ah yes, the permanent generation is reluctant to have its garbage
collected (the clue is in the name). One of the EJB servers (BEA?) had a
problem running on Sun's JRE because it could throw OutOfMemoryError
despite having plenty of memory available.Apparently, it used to be the
case that running out of memory for the permanent generation didn't
trigger gc, so you need create transient data to force a collection
(proper details are on the Bug Parade somewhere).

In today's world, System.gc does not appear to collect from the
permanent generation. Naive memory measurements are therefore misleading.


The folk wisdom that inner classes are really expensive is hogwash.


Still, it seems inefficient of the JVM to allocate permanent generation
memory in such a manner.

Tom Hawtin


import java.io.*;

class Gen {
public static void main(String[] args) throws IOException {
final int inners = Integer.getInteger("inners");
File dir = new File("test"+inners);
if (!dir.mkdir()) {
throw new Error("mkdir: "+dir);
}
String pkg = "mylongpackagenameandsomerandompadding";
File pkgDir = new File(dir, pkg);
if (!pkgDir.mkdir()) {
throw new Error("mkdir: "+pkgDir);
}
String cls = "Test"+inners;
Writer out = new BufferedWriter(new FileWriter(new File(
pkgDir, cls+".java"
)));

out.write(
"package "+pkg+";\n"
+"\n"
+"import java.awt.*;\n"
+"import java.awt.event.*;\n"
+"import javax.swing.*;\n"
+"\n"
+"class "+cls+" {\n"
+" public static void main(String[] args) throws Exception {\n"
+" final JButton button = new JButton();\n"
+"\n"
);
for (int ct=0; ct<inners; ++ct) {
out.write(
" button.addActionListener(new ActionListener() {\n"
+" public void actionPerformed(ActionEvent event) {\n"
+" button.setText(\""+ct+"\");\n"
+" }\n"
+" });\n"
);
}
out.write(
"\n"
+" System.gc();\n"
+" Runtime runtime = Runtime.getRuntime();\n"
+" System.out.println(\n"
+" \""+inners+" - \"+\n"
+" \"freeMemory: \" +runtime.freeMemory() +\", \"+\n"
+" \"maxMemory: \" +runtime.maxMemory() +\", \"+\n"
+" \"totalMemory: \"+runtime.totalMemory()+\", \"\n"
+" );\n"
+" Thread.currentThread().join();\n"
+" }\n"
+"}\n"
);
out.close();
}
}
 
T

Thomas Hawtin

Thomas said:
In today's world, System.gc does not appear to collect from the
permanent generation. Naive memory measurements are therefore misleading.

Playing around with it some more, seems I want to be measuring non-heap
memory. I get around 1K or so per anonymous inner class with -server. I
shall play some more.

Tom Hawtin
 
T

Thomas Hawtin

Chris said:
Thomas Hawtin wrote:




?

Details, please ;-)

For lengths greater than zero:

len * (41 * 41 * 41) +
cs[start] * (41 * 41) +
cs[start + len - 1] * 41 +
cs[start + (len >> 1)]

So it's based on the length, first character, last character and middle
character. I had class names like Test1000, Test1010,, Test1020, etc.
Not good. Even the JDK 1.02 String hashCode was better than that.
Sampling does not pay when it come to hash codes.

The patched version seemed to run much faster. It actually completed
before being killed.

Tom Hawtin
 
S

steve

Hi,
Could anyone help me with this problem. I have an action listener
associated with a number of buttons. I can get the action listener to
work, but what code do I need to findout which button was pressed.

This is the layout of the action listener class.

import java.awt.event.*;
import java.awt.Component;

public class ButtonListener implements ActionListener
{
public void actionPerformed (ActionEvent e)
{

}

}

Thanks in advance.

Ben.


something like this

public class ShipmentsCard1 extends JPanel implements ActionListener {

Quit_BUTT.setText("Quit");
Quit_BUTT.setBounds(new Rectangle(615, 10, 90, 25));
Quit_BUTT.setFont(new Font("Arial", 0, 9));
Reports_BUTT.setText("Reports");
Reports_BUTT.setBounds(new Rectangle(501, 10, 110, 25));
Reports_BUTT.setFont(new Font("Arial", 0, 9));


Quit_BUTT.addActionListener(this);
Reports_BUTT.addActionListener(this);



public void actionPerformed(ActionEvent evt) {
Object source = evt.getSource();

if (source == Quit_BUTT) {
Killprogram();
}

if (source == Reports_BUTT) {
//this is working (21/12/2005)
printRecords();
}

}

}

where possible keep it all together in 1 routine, adding listener classes all
over the place as separate items makes code maintanance a PIG.
 
I

IchBin

[snip code]

If I implement ActionListener. I usually do it this way:

public class ShipmentsCard1 extends JPanel implements ActionListener {
private final String QUIT = "Quit";
private final String REPORT = "Reports";

Quit_BUTT.setText(QUIT);
Quit_BUTT.setBounds(new Rectangle(615, 10, 90, 25));
Quit_BUTT.setFont(new Font("Arial", 0, 9));
Quit_BUTT.setActionCommand(QUIT);
Quit_BUTT.addActionListener(this);

Reports_BUTT.setText(REPORT);
Reports_BUTT.setBounds(new Rectangle(501, 10, 110, 25));
Reports_BUTT.setFont(new Font("Arial", 0, 9));
Reports_BUTT.setActionCommand(REPORT);
Reports_BUTT.addActionListener(this);
 
C

Chris Uppal

Thomas said:
So it's based on the length, first character, last character and middle
character.

Dear Gods!

The patched version seemed to run much faster. It actually completed
before being killed.

Dunno what you're complaining about -- even with 3000 inner classes it still
compiled in only a little over two minutes ;-)

-- chris
 
C

Chris Uppal

Thomas said:
Playing around with it some more, seems I want to be measuring non-heap
memory. I get around 1K or so per anonymous inner class with -server. I
shall play some more.

I get the same using the 1.5 client VM. Each inner seems to add around 1.1K or
1.2K to the what jconsole/JMX calls the "Perm Gen" memory pool. (I haven't
been able to find any info relating the "Perm Gen" to the "Perm Gen [shared
ro]" and "Perm Gen [shared rw]" pools.)

They add some load to the code-cache too, but that's to be expected since there
are actually more methods... Presuming that the choice is between putting a
fixed amount of code in either an dedicated inner class or somewhere else, I
don't think the code size is relevant. Sadly the monitoring doesn't seem to
work with -Xint.

Other than that, they don't seem to add any load to reported memory use.

-- chris
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,152
Latest member
LorettaGur
Top