Persisting object value in Java Swing application - java

I have a swing UI having two buttons : 1. Loading database values to Hashmap 2. Comparing input values to database values.
Previously both the operations were done using the same button so the Hashmap was getting populated and the inputs were compared correctly. But now its not so.
After debugging I came to know that the hashmap values are null as the values are lost during the second operation.
How to approach this problem. So that the hash map values persist while i click the second button.
Code Example:
Button1: Loading-
LoadMaps = new JButton( new AbstractAction("LoadMaps") {
#Override
public void actionPerformed( ActionEvent e ) {
DRGCalc t = new DRGCalc();
t.loadHashMaps();
}
});
Button2: Calculation-
public void actionPerformed(ActionEvent evt) {
DRGCalc d = new DRGCalc();
int i = d.calculateDRG(Codes);
}
As t and d are two seperate objects so the values in t wont persist when I am clicking d. For this I have included the method used in button 1 inside the calulateDRG call and its working fine but I want both to be separate. How to do this?
Thanks

DRGCalc t = new DRGCalc();
This object only exist within the ActionListener. If you want the object to be available to other ActionListeners or other methods in your class then you need to make it a class variable. So in your class you need to define:
DRGCalc t;
Then in the ActionListener you change the code to:
t = new DRGCalc();

Related

Is there a way to add interface instances to an ArrayList in Java?

I found this
In which the accepted answer is almost perfect, but I would like to instead add the elements to an ArrayList. Is this possible?
I'll try to be concise: I'm creating a JavaFX application and I have an ArrayList containing all my TextFields. I used this list to add an event handler for the Action event to each field, and this handler calls a method that moves focus to the next field in the list (this way the user can press return and will navigate to the next field automatically).
In the same loop I also add an event listener to each field, so that if a field loses focus another method is called to update the form. In this way the user can navigate however they choose (return, tab, mouse click, etc.), and the form will update automatically without the need for a button click when they are finished entering data.
Now, in the update method, I determine which field triggered the event and validate the text in the field and parse a double from it. I then need to do something with that data. Here is where I want to use my ArrayList of "worker functions." I can simply create a parallel ArrayList that matches the index order of the field traversal ArrayList, and call the correct update method.
I want to do it this way because each TextField is tied to a specific member of a specific object for example - the TextField qtyOrdered would be tied to the workOrder.qtyOrdered member, and the TextField materialWidth would be tied to the masterRoll.materialWidth member. These objects would of course have their own accessors and mutators, so I wanted to use the interface to create all these methods beforehand and call the correct one based on the index of the TextField.
I want something like this (pseudocode):
ArrayList<Worker> workerMethods = new ArrayList<>();
workerMethods.add(new Worker() {
public void work(double input) {
workOrder.setQtyOrdered(input);
}
});
//Add remaining methods...
method updateForm(TextField caller)
{
get callerIndex;
// validate user input
if (valid)
workerMethods.get(callerIndex).work(input);
}
In fact, using the method I linked to, this works with arrays like so:
workerMethods[callerIndex].update(callerValue);
However, when I use the same syntax for adding to an ArrayList instead it obviously does not work.
I would like to use an ArrayList instead of an array if possible. This is because some fields in the form are removed from the traversableFields ArrayList when they are deactivated so that field traversal will skip these fields when they are hidden from view, and resume in the correct order when they are visible. For example, if the user wants to estimate the length of material on the master roll, they can click a CheckBox to show those fields.
The Action event handler for that CheckBox would then call my updateControls() method which would enable the required fields, set them to visible, and add them to the list of traversable fields. If they uncheck it, the reverse happens.
If I am using an array to store my update methods, the indexes may not match the indexes of my traversableFields List at any given time.
Edit: Added my actual code below (this is a simplified version I am using in a small test environment).
Code for creating the list of traversable TextFields:
// ArrayList of traversable TextFields for form navigation.
private ArrayList<TextField> traversableFields = new ArrayList<>();
// Add all TextFields to the ArrayList.
traversableFields.addAll(Arrays.asList(field1, field2, field3));
// Loop through the ArrayList to add handlers/listeners.
for (int i = 0; i < traversableFields.size(); i++) {
// Get the Control at index i in the ArrayList.
TextField currentControl = traversableFields.get(i);
// Add an event handler so that when the user presses return we can
// move to the next field in the ArrayList.
currentControl.addEventHandler(ActionEvent.ACTION, e ->
moveToNextField(e));
// Add a listener so that if a field loses focus we update the form.
currentControl.focusedProperty().
addListener((obs, wasFocused, isNowFocused) ->
{
if (!isNowFocused) {
updateForm(currentControl);
}
});
}
Code for creating the array of worker methods:
interface Update { public void update(double input); }
class Label1 { public void update(double input) { label1.setText(String.valueOf(input)); } }
class Label2 { public void update(double input) { label2.setText(String.valueOf(input)); } }
class Label3 { public void update(double input) { label3.setText(String.valueOf(input)); } }
Label1 l1 = new Label1();
Label2 l2 = new Label2();
Label3 l3 = new Label3();
Update[] updateFunctions = new Update[] {
new Update() { public void update(double input) { l1.update(input); } },
new Update() { public void update(double input) { l2.update(input); } },
new Update() { public void update(double input) { l3.update(input); } }
};
The snippet above is basically exactly what they did in the link I posted. As I mentioned earlier, this works. I can call updateFunctions[callerIndex].update(callerValue); and it does what I want. Here is the method called by the event handler:
// Move to the next field in the form. Called by the Action Event for each
// field in the traversableFields ArrayList.
private void moveToNextField(ActionEvent event)
{
// Get the TextField that triggered the event.
TextField caller = (TextField)event.getSource();
// Get the index of this Control from the ArrayList.
int callerIndex = traversableFields.indexOf(caller);
// If we have reached the end of the list then we move to the
// first field in the list.
if (callerIndex == traversableFields.size() - 1)
traversableFields.get(0).requestFocus();
// Otherwise move to the next field.
else
traversableFields.get(++callerIndex).requestFocus();
}
and here is the method called by the focus listener:
// Update the form. This will contain the majority of functional code
// and will be called automatically when any TextField loses focus.
private void updateForm(TextField caller)
{
// Get the index of the TextField
int callerIndex = traversableFields.indexOf(caller);
// Get the CSS id of the TextField for testing purposes.
String callerID = caller.getId();
// Get the TextField contents.
String callerText = caller.getText();
// Flag variable.
boolean fieldEmpty = callerText.equals("");
// Double for storing parsed input.
double callerValue = 0;
// If the field is not empty, ensure that it contains valid data before
// proceeding.
if (!fieldEmpty)
{
try
{
callerValue = Validation.getDouble(callerText);
updateFunctions[callerIndex].update(callerValue);
clearError(caller);
}
catch (Exception e)
{
// If the input was invalid, alert the user and move focus
// back to the offending TextField.
System.out.println("Invalid input.");
markEntryInvalid(caller);
caller.requestFocus();
}
}
// Trace statements.
System.out.println("updateForm() called by " + callerID);
System.out.println("Parsed value was " + callerValue);
}
However, I want to use an ArrayList instead of an array. But if I do this:
ArrayList<Update> updateMethods = new ArrayList<>();
updateMethods.add(new Update() { public void update(double input) { l1.update(input); } });
I get <identifier> expected error.
If I understand your question correctly, what you want to know is how to initialize an ArrayList with a given collection of values?
That would be done like this:
List<Workers> myWorkers = new ArrayList<>(
Arrays.asList(
new Worker() { ... },
new Worker() { ... }
)
);
Arrays.asList(element1, element2, ...) returns an immutable list of these elements. And the constructor of ArrayList can take a Collection to initialize the list.
Of course, you can also create the list and add single elements. The resulting list is the same:
List<Workers> myWorkers = new ArrayList<>();
myWorkers.add(new Worker() { ... });
myWorkers.add(new Worker() { ... });
In both cases, the resulting list can be modified using add and remove methods.
Two notes on the usecase, though:
First, a Map might be better suited for your usecase, because you don't need to take care about indexes:
// initialization:
Map<TextField, Worker> workers = new HashMap<TextField, Worker>();
workers.put(textfield1, worker1);
workers.put(textfield2, worker2);
// ...
void updateForm(TextField caller) {
workers.get(caller).work();
}
Second, if your Worker interface only has one method, since Java 8 you can use it as a functional interface with a closure. So the initialization would look like this:
Map<TextField, Worker> workers = new HashMap<TextField, Worker>();
workers.put(textfield1, input -> { /* do something with input here */ });
workers.put(textfield2, input -> { /* do something with input here */ });
And maybe your Worker interface is even not needed and you can just use Consumer<InputType> instead.
You can create List<Runnable> and execute the code in the current thread or in the parallel thread:
List<Runnable> workerMethods = List.of(
() -> System.out.println("worker 1"),
() -> System.out.println("worker 2"));
// execute code in the current thread
workerMethods.get(0).run(); // worker 1
// execute code in a new thread
new Thread(workerMethods.get(1)).start(); // worker 2
Similarly, you can create Map<String, Runnable>:
Map<String, Runnable> workerMethods = Map.of(
"w1", () -> System.out.println("worker 1"),
"w2", () -> System.out.println("worker 2"));
// execute code in the current thread
workerMethods.get("w1").run(); // worker 1
// execute code in a new thread
new Thread(workerMethods.get("w2")).start(); // worker 2
Might I suggest an entirely different approach?
Why not use the user data field of the TextField to point to your own object that can handle all of your needs.
e.g.
class FieldContext {
TextField previous;
TextField next;
Update updater;
// add whatever else you need, e.g. validation interface etc.
}
so when you get an event from the TextField you can just call:
FieldContext fieldCtx = (FieldContext)((TextField)event.getSource()).getUserData();
and then you are free to handle whatever specific event processing is needed having the context information for the TexTField.
I find a lot of people overlook the fact that you have a field for user data on the controls. I find it can simplify things quite a bit

Transporting values in arrays within scopes in Swing - java

my goal is to be able to draw graphs and then save its values if required.
In the image above, I choose from the comboBox a specific type of graph to draw, except for Clear, which just clears the graph that is shown. This is already working correctly.
I have an arrayList of UserPattern(I created) objects that contains a string, a double and a double array.
I want to store the values from the graph in some variable (i'm currently using a double array) to use it later on.
With the double array I've had problems with the passing of values, since when I press "Save Pattern" it keeps the latest values of the graph (the last graph shown) and inputs it on every element of the UserPattern List that I have previously saved. So, even if I save multiple patterns, they all keep the value of the last save.
This is the code I use to store the values in the ArrayList:
private void readAndInsertPatternValues(List<UserPattern> patternLi, double[] graphValue) {
UserPattern tempUserPattern = new UserPattern(typePattern);
//extra code
tempUserPattern.setMonthlyConsump(consTemp);
tempUserPattern.setNameID(patternName);
tempUserPattern.setPatternValues(graphValue);
patternLi.add(tempUserPattern);
System.out.println("Inserted: ");
System.out.println(tempUserPattern);
}
}
I call this method within a mouse event on the button "Save Pattern":
JButton btnSaveUserPattern = new JButton("Save Pattern");
btnSaveUserPattern.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
if(!((comboBoxPattern.getSelectedItem()).equals(UserPattern.PatternType.CLEAR)))
readAndInsertPatternValues(patternList, patternValue);
for(UserPattern upTemp : patternList) {
System.out.println("Inside the Pattern List:");
System.out.println(upTemp.toString());
}
}
});
btnSaveUserPattern.setFont(new Font("Tahoma", Font.PLAIN, 13));
btnSaveUserPattern.setEnabled(false);
Also, I get the values that create the graph in the event from selecting an option of the combobox:
comboBoxPattern = new JComboBox<UserPattern.PatternType>();
comboBoxPattern.setFont(new Font("Tahoma", Font.PLAIN, 13));
comboBoxPattern.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
//this method creates the graphs, so I send the array "patternValue" to "get" the values.
printPatternGraph(comboBoxPattern, chartPanel, "User Pattern for Energy Consumption", "Hours", "Energy Consumption(Wh)", true, patternValue);
btnSaveUserPattern.setEnabled(true);
}
});
I initialized the patternValue array as a local variable in the method that calls and uses the above mentioned methods as such:
double[] patternValue = new double[1440];
With all this, happened the problem in transporting values. At the "insertion time", the console showed the correct values, however, when I clicked on the "Save Pattern" button, which shows all the objects in the UserPattern list, the graph values from the previously saved graphs were equal to the one I saved last. (The last one I saved corrupted all the others).
I tried to change the way of passing values and changed the method "printPatternGraph" to return a double[] array, and made like this:
patternValue=printPatternGraph(comboBoxPattern, chartPanel, "User Pattern for Energy Consumption", "Hours", "Energy Consumption(Wh)", true);
This, however, brought me the error,
Local variable patternValue defined in an enclosing scope must be final or effectively final.
Therefore, I tried making "patternValue" a global variable . This actually solved the problem, but I don't think that this is the best solution (I've read multiple times that global variables are "bad coding".
This way, which way do you think I should implement this?
Thanks for your attention and sorry for the long post,
nhekas
SOLUTION:
I understood what was wrong! Sorry to bother you guys.
My problem, was, that when I added the double array to the ArrayList, I did it like this:
patternLi.add(graphValues);
This, instead of storing the values inside the graphValue array, was storing the reference to it. Therefore, when I wanted to create a different graph, the reference to the graph was the same, but changed the values.
I had to do the following:
new double[] arrayTemp= new double[1440];
for ( int i=0; i<1440;i++) {
arrayTemp[i]=graphValues[i];
}
patternLi.add(arrayTemp);
This way, it worked! Because, since arrayTemp is local, is created everytime I call the method and passes the correct values.
Thanks for all your input guys !
nhekas

Why the Item deleted from an array but isn't deleted from my table?

I've put together a few methods that are suppose to delete a searched item from an array and the data from the array is also being put into a JTable through a method called createLoginTable().
When my delete button actionListener Method is carried out the element or login is successfully deleted from the array: 'listOfLogins' but the element does not appear to be deleted from the JTable as it is still there.
Here are the methods starting with the actionListener:
if(e.getSource()==deleteLoginButton)
{
int loopNo = list.nextLogin; ///Variables used in the 'removeLogin' Method
String foundLogin = list.listOfLogins[foundLocation].toString();
Login[] loginList = list.listOfLogins;
LoginList list = new LoginList(); //The 'list' is wiped
list.removeLogin(loginList, foundLogin, loopNo);
list.writeLoginsToFile(); //Writes logins to file (not integral to the array)
String[][] loginTableLogins = new String[50][2]; //Wipes the JTable Array
createLoginsTable(); //Creates the JTable
searchLoginButton.setEnabled(true);
editLoginButton.setEnabled(false);
deleteLoginButton.setEnabled(false);
addLoginButton.setEnabled(true);
}
This is the 'removeLogin' Method (This is in a seperate 'list' class):
public void removeLogin(Login[] array, String unwantedLogin, int loop)
{
for(int i=0;i<loop;i++)
{
String currentLogin = array[i].toString();
if(!currentLogin.equals(unwantedLogin))
{
Login login = new Login();
addLogin(array[i]);
}
}
}
plus 'addLogin' Method (although i am assured this is not the source of my issue):
public void addLogin(Login tempLogin)
{
listOfLogins[nextLogin] = tempLogin;
System.out.println(listOfLogins[nextLogin]);
nextLogin++;
System.out.println(nextLogin);
}
And the 'createLoginsTable' method:
public void createLoginsTable()
{
for(int i=0;list.nextLogin>i;i++)
{
loginTableLogins[i] = list.listOfLogins[i].toArray();
System.out.println(list.listOfLogins[i].toString());
}
JTable loginsTable = new JTable(loginTableLogins, loginTableTitles);
JScrollPane loginsScrollPane = new JScrollPane(loginsTable);
loginsScrollPane.setBounds(400, 200, 200, 250);
testPanel.add(loginsScrollPane);
}
I have used 'System.out.println's so I am 99% certain that the element has been removed from the array (it is also apparent through my writeLoginsToFile Method) So I hope this information helps.
Your code is a little bit hard to decipher, next time maybe put in also the enclosing class, or some details about that class. What does the following line do:
LoginList list = new LoginList(); //The 'list' is wiped
You say the list is wiped, I think what is does is: it declares a list local variable and assigns a new object to it (and it masks the other list variable which you used a few lines earlier). Now, in the createLoginsTable() method you don't have this local variable, you have the "list" which I guess is a public field in your class. Now what you can do, is or pass the local list variable to the above function as a parameter createLoginsTable(list) or try the wiping line without the declaration so only:
list = new LoginList(); //The 'list' is wiped
Anyway, your code seams a little bit troubled it, maybe you should refactor it a little bit. Hope it helps.
You're not returning the table after you delete the item.
When you call the method to delete it and write out the table, that table is not returned after you remake the table.
Take this:
JScrollPane loginsScrollPane = new JScrollPane(loginsTable);
Bring it outside of your method. What I think might be happening is when you create your loginsScrollPane locally inside the method, it's not being added properly to your testPanel.
I think what might be happening is when you add it, and the method ends it's loosing that data that is contained. Declare your scrollpane, and your jtable where you declare your frame.

JTextField getText() not working

I've been looking all over, and i cant find anyone who can solve this problem. I'm making a game, and in that game, i have editable controls. the controls window is a seperate JFrame, and when i click the confirm button, it is supposed to write the items in the JTextFields (holding the controls) to a file. but that wasnt working, so instead i have it print the arraylist that holds the values. here is the code:
public void writeControls() {
ArrayList<String> al = new ArrayList<String>();
al.add(up.getText());
al.add(down.getText());
al.add(left.getText());
al.add(right.getText());
al.add(jump.getText());
al.add(duck.getText());
al.add(attack.getText());
for (int i = 0; i < al.size(); i++) {
System.out.println(al.get(i));
}
System.exit(0);
}
the problem is this: if i change the final JTextField attack or any other one for that matter, and click submit, the system prints out the default controls. for example, if the JTextFields have the values w,a,s,d,r,t,q and i change the value q to i, it prints out q. what am i doing wrong? thanks in advance!
EDIT 1:
code for the textfields, and the FILES.... is simply a string stored in a different class. the class setText() is below the textfields.
up = new JTextField(setText(FILES.controlsFileFinalDir, 1));
down = new JTextField(setText(FILES.controlsFileFinalDir, 2));
left = new JTextField(setText(FILES.controlsFileFinalDir, 3));
right = new JTextField(setText(FILES.controlsFileFinalDir, 4));
jump = new JTextField(setText(FILES.controlsFileFinalDir, 5));
duck = new JTextField(setText(FILES.controlsFileFinalDir, 6));
attack = new JTextField(setText(FILES.controlsFileFinalDir, 7));
public String setText(String fileDir, int lineNum) {
String txt = "";
txt = io.readSpecificLine(fileDir, lineNum);
txt = switchCase(txt);
return txt;
}
switchcase() is only taking what you have written in the text file that these are getting the values from, and translating them. so if the value is 0, it is turned into Space, etc. io.readSpecificLine(); is only to get the line of text from the file. does this help?
EDIT 2:
i just was dinking around and found out that if i set the JTextField text by using setText(""); then use getText(); it works. so the problem is that when i change it manually, and use getText(); it wont work. Why?
To update the text to a currently existing JTextField, I would establish the JTextField as a class variable, and create a setter/getter method to adjust it (which I'm assuming you're doing).
According to your methods, you would use something like:
up.setText(setText(FILES.controlsFileFinalDir, 7));
Edit: **The first setText is the JTextField.setText, the second setText is your public method you posted. I'm assuming your second getText() isn't working because you're probably not setting the text correctly.
Without seeing more code, I can't really give a better guess.
The main possibilities:
(1) The text fields have their editable property set to false.
(2) You are creating multiple copies of the JTextFields, then editing a new one on the screen, but referring to the old one when you get the value.
(3) You have a ValueChanged or LostFocus event handler that is resetting the text fields to their defaults
(4) It is actually JFormattedTextField not a JTextField
If I was you, I would try to debug the programm. You will probably do some Mistake in your code, you won't be able to see, by just checking the code.
For example in which order do you call the functions and so on, maybe you have a fault here, or maybe you have several threads, so you try to read the Textfields without even set them and so on ... It's hard to say without reviewing the whole Code.
So if you use eclipse you can follow this link for an explanation on how to debug: http://www.vogella.com/articles/EclipseDebugging/article.html
Netbeans or any other IDE should support debugging as well.
This may seem like a strange thing to suggest, but I think this is an issue with pointers. If you create a new string before passing it in, JTextField will be able to change it internally and return what you expect when asked for the modified value.
down = new JTextField("" + setText(FILES.controlsFileFinalDir, 2));
// or
down = new JTextField(new String(setText(FILES.controlsFileFinalDir, 2)));
You might want to try the following:
create a class Test.java
import java.util.ArrayList;
import javax.swing.JTextField;
public class Test implements Runnable {
private ArrayList<JTextField> textFields = null;
private ArrayList<String> stringList = null;
public Test(ArrayList<JTextField> textFields, ArrayList<String> stringList) {
this.textFields = textFields;
this.stringList = stringList;
}
#Override
public void run() {
for ( JTextField textField : this.textFields )
this.stringList.add( textField.getText() );
}
}
and then, at the place where you use the "getText() method .. "
do the following...
ArrayList<JTextField> textFields = new ArrayList<JTextField>();
// add all the JTextField to textFields
ArrayList<String> stringList = new ArrayList<String>();
Test test = new Test( textFields, stringList );
SwingUtilities.invokeLater( test );
// check if the stringList is populated.
If this work, then what I believe is that, for some reason, the JTextField hasn't finished
"setting" the text, and before it finishes your getText() was called. I've had similar problems before, and this solved my problem that time, but still, this might not be the perfect solution.
First, you should change your "setText()" method name to something like "getTextFromFile()" it would be more readable
Then, if you are setting and reading the new text in different threads, my bet is that the setText() is taking long to return, because it is accessing the file system, while the method that read the values run instantly
I would try to do run a little test:
public void test(){ // must be run after the JTextFields be initialized
up.setText("TEST")
System.out.println(up.getText());
up.setText(setText(FILES.controlsFileFinalDir, 1));
System.out.println(up.getText());
}
If the test() prints the correct values, then we can assume that if you set and read the new value in the same thread it works fine
The other test I would do is:
public void testThread(){
new Thread(){
public void run(){
while(true){
if(up!=null){
System.out.println(up.getText());
}
try{
Thread.sleep(1000);
}catch(Exception e){
e.printStackTrace();
}
}
}
}.start();
}
It will print the value of up each 1 second, so that you can see if after some time you get the new value. If it does, then the answer is: Your setText() is taking long to run and you are reading the value before the new value is set
SOLUTION
none of the above answers were working for me, so i finally decided to just start over with that class. the few things i changed were the way i made the JTextFields. I made them as an array instead of individual objects. Second is the way i put what they say. When i initialized them, i was unable to get them to create WITH the text in the parameters. so i had to do that seperately. i changed some of the method names so as to reduce future confusion, and it worked! so im not sure what was up with that, maybe it was the way i did it, maybe just a fluke. it happens sometimes, so im sorry for the delay and waste of your time! thanks for all the answers anyway!
Try this:
textbox.setText(setFile(args)); // your function for set file

Java/JavaFX2: dynamic GUI, detect which button was pressed, extract id

I'm a newbie in Java/JavaFX (I began yesterday evening). I'm building a dynamic GUI (crud) reading off a MySQL database.
I managed to display the data in a table and add a button next to each row.
Since the number of buttons is variable, I want to define only a common eventhandler.
The problem is that whenever I use event.getSource() (it's an ActionEvent) and display it, I get something like "Button[id=0, styleClass=button].
Question 1: Is there any way I could put the id in a variable? I can't get it out of the object.
As far as I know, I have to use the id, since I can't do something like this "if(event.getSource() == somebutton) {...}" since every generated button had the same variable name.
Now, this is the loop (inside a method called make_buttons) that builds the buttons. n_buttons is the number of buttons I want to build.
for(int counter = 0; counter < n_buttons; counter++){
String newtext = new String("btn"+counter);
Button btn = new Button();
btn.setText(newtext);
btn.setId(Integer.toString(counter));
btn.setOnAction(myHandler);
grid.add(btn,0,counter);
}
Note that I'm placing the buttons on a gridpane one on top of the other.
Before that part I have my handler:
final EventHandler<ActionEvent> myHandler = new EventHandler<ActionEvent>(){
public void handle(final ActionEvent event) {
Object new_output = event.getSource();
System.out.println(new_output);
event.consume();
}
};
Question 2: so, how can I differentiate which button fired the event in my particular case?
I know quite a few programming languages (Matlab, R, Python, C, Assembly, etc... but I'm a hobbyist), but it's the first time I'm working with GUI elements (except web languages and ActionScript 3).
In actionscript I could just do something like event.getCurrentTarget and the use it exactly as if it were the object itself to read the id, properties, etc.
I looked everywhere and couldn't find anything (maybe my terminology was a bit approximative...).
If I understand your question correcty, you can simply access the clicked button in you handle method with the following code:
Object source = event.getSource();
if (source instanceof Button) { //should always be true in your example
Button clickedBtn = (Button) source; // that's the button that was clicked
System.out.println(clickedBtn.getId()); // prints the id of the button
}

Categories