action listener in another class - java - java

it is possible to have two class, and in one something like
arrayButtons[i][j].addActionListener(actionListner);
and in another
ActionListener actionListner = new ActionListener() {
public void actionPerformed(ActionEvent e) {
for (int j = 0; j < arrayButtons.length; j++) {
for (int i = 0; i < arrayButtons[j].length; i++) {
if (arrayButtons[j][i] == e.getSource()) {
if ((gameNumber == 2) && (playHand.getNumberOfCards() == 0)) {
if (player[j].getCard(i).getSuit() == Suit.HEARTS.toString() && player[j].hasSuitBesideHearts())
//second game
messageOnTable("xxx");
else{
arrayButtons[j][i].setVisible(false);
test[j].setIcon(player[j].getCard(i).getImage());
pnCardNumber[j].setText(Integer.toString(player[j].getCard(i).getNumber()));
pnCardName[j].setText(player[j].getCard(i).toString());
pnCardSuit[j].setText(player[j].getCard(i).getSuit());
playHand.addCard(player[j].getCard(i), j);
player[j].removeCard(i);
}
}
}
//and more
the reason of that is because i need to separate the button (swing) to the action listener
how i can do ?
thanks

Not only it is possible to separate these two, it's also recommended (see MVC pattern - it's very much about separating screen controls like buttons, and the logics of your program)
The easiest way that comes to my mind is to do write a named class that implements ActionListener interface, something like this:
public class SomeActionListener implements ActionListener{
private JTextField textField1;
private JComboBox combo1;
private JTextField textField2;
//...
public SomeActionListener(JTextField textField1, JComboBox combo1,
JTextField textField2){
this.textField1=textField1;
this.combo1=combo1;
this.textField2=textField2;
//...
}
public void actionPerformed(ActionEvent e) {
//cmd
}
}
And then add it to your buttons:
ActionListener actionListener = new SomeActionListener(textField1, combo1, textField2);
someButton.addActionListener(actionListener);

To answer: "my problem is that action listener have many variables of swing like buttons for example,so, when i change to another class, i have problems with that"
Your action listener class could have a constructor that takes a parameter of the type of the view class:
public class Listener implements ActionListener {
private final MyViewClass mView;
public Listener(MyViewClass pView) {
mView = pView;
}
public void actionPerformed(ActionEvent e) {
// can use mView to get access to your components.
mView.get...().doStuff...
}
}
Then in your view:
Listener l = new Listener(this);
button.addActionListener(l);

you can do it easily by using nested classes,
but i think the best way is pass the parent object as a parameter to the construct of object and using it as an action handler;
//**parent class - Calculator **//
public class Calculator extends JFrame implements ActionListener{
private DPanel dPanel;
private JTextField resultText;
public Calculator(){
// set calc layout
this.setLayout(new BorderLayout(1,1));
dPanel = new DPanel(this); // here is the trick ;)
}
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
resultText.setText(command);
// **** your code ****/
}
}
//**inner class - DPanel**//
public class DPanel extends JPanel{
private JButton digitsButton[];
private JButton dotButton,eqButton;
public DPanel(Calculator parent){
//layout
this.setLayout(new GridLayout(4,3,1,1));
// digits buttons
digitsButton = new JButton[10];
for (int i=9;i>=0;i--){
digitsButton[i] = new JButton(i+"");
digitsButton[i].addActionListener(parent); // using parent as action handler ;)
this.add(digitsButton[i]);
}
}
}

It's a bit off topic but you should definately not use the == operator to compare Strings as you appear to be doing on this line:
if (player[j].getCard(i).getSuit() == Suit.HEARTS.toString()
This is because Strings are pointers, not actual values, and you may get unexpected behaviour using the == operator. Use the someString.equals(otherString) method instead. And also
"String to compare".equals(stringVariable)
is alot better than the other way around
stringVariable.equals("String to compare to")
because in the first example you avoid getting a NullPointerException if stringVariable is null. It just returns false.

Yes, it can be done. It's very simple; in one class you have your buttons, in the other class you just need to implement an ActionListener and just make your //cmd
to separate that button's function. To do this, you need to use e.getActionCommand().equals(buttonActionCommand).
Sample code:
public class Click implements ActionListener{
public Click(
//input params if needed
){
}
public void actionPerformed(ActionEvent e) {
if( e.getActionCommand().equals(buttonActionCommand){
//cmd
}
}
}
To add that listener on your button just do:
buttonTest.addActionListener(new Click());

Related

Java enter key the same as submit button?

What the program is supposed to do is to mimic the "spin" button with the enter key. The program works and it doesn't crashes but eclipse console is giving me a "Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: javax.swing.JTextField cannot be cast to javax.swing.JButton" error.
//.. gui code
spin = new JButton("Spin");
bet = new JTextField("");
play p = new play();
spin.addActionListener(p);
keys k = new keys();
bet.addKeyListener(k);
}
private class play implements ActionListener{
public void actionPerformed(ActionEvent e) {
JButton src = (JButton) e.getSource();
if(src.equals(spin)) {
//do something
}
}
private class keys implements KeyListener{
#Override
public void keyTyped(KeyEvent e) {
char c= e.getKeyChar();
if(c == KeyEvent.VK_ENTER) {
spin.doClick();
}
}
//.. the other override methods
}
EDIT
there are 2 more buttons, I just didn't include them since they worked fine and functioned differently.
JTextField has a KeyListener because I was filtering out numbers from letters so I would consume the event. Can't have a user bet with letters right?
I would guess that your ActionListener is receiving events from multiple objects, one of which is a JTextField. The exception occurs when you try to cast this object to JButton:
(JButton) e.getSource();
There may be a better solution but from what you've shown us the easiest way to prevent the exception is to check that the object generating is an event is an instance of JButton before casting:
private class play implements ActionListener{
public void actionPerformed(ActionEvent e) {
Object src = e.getSource();
// Check type before casting
if (src instanceof JButton) {
JButton bsrc = (JButton)src;
if(bsrc.equals(spin)) {
//do something
}
}
}
}
First, don't use KeyListener for this task, JTextField already supports ActionListener and you could make use of JRootPane's "default button" support as well, so a number of better solutions are available.
You should also take advantage of the actionComamnd support of the ActionEvent (and ActionListener), which will mean you don't have to cast the source, which is safer and makes the solution more re-usable (as it's decoupled).
For example...
Play p = new Play();
spin = new JButton("Spin");
spin.setActionCommand(Play.COMMAND);
bet = new JTextField("");
bet.setActionCommand(Play.COMMAND);
spin.addActionListener(p);
bet.addActionListener(p);
//...
private static class Play implements ActionListener {
public static String COMMAND = "Spin";
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals(COMMAND)) {
//do something
}
}
}
Alternatively, you could make use of the existing Actions API. This allows you to design a self contained unit of work that can be applied directly to a number of Swing components (which already support the ActionListener API), but which are also self configurable, neat...
private class SpinAction extends AbstractAction {
public SpinAction() {
putValue(NAME, "Spin");
}
#Override
public void actionPerformed(ActionEvent event) {
// Spin me baby
}
}
And then simply apply it...
SpinAction action = new SpinAction();
spin = new JButton(action);
bet = new JTextField("");
bet.setAction(action);
See How to use actions for more details

How to repaint JPanel from outside its parent JFrame?

I can add/remove elements to/from a panel and repaint it when the method used to fill the panel is called by one of its parent JFrame events, but I can not repaint it by events from other classes even if their sources have been added to it, or that is how I understand the problem for now.
I want to understand what is going on here, Thank you.
Main Class
public class Principal extends JFrame implements ActionListener{
private static Principal instPrincipal = null;
private SubClass subClassInst =new SubClass();
public JPanel panelPrincipal;
public static Principal getInstance() {
if (instPrincipal != null)
return instPrincipal ;
else {
instPrincipal = new Principal ();
return instPrincipal ;
}
}
public void actionPerformed(ActionEvent event) {
Object source = event.getSource();
try {
if(source == btnSub)
{
subClassInst.fillPanelPrincipal();
}
}
catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
Sub Classes Example
public class SubClass implements ActionListener {
private JPanel tempPanel;
private JButton btnSave;
private Principal instPrincipal;
public void fillPanelPrincipal() {
instPrincipal = Principal.getInstance();
instPrincipal.panelPrincipal.removeAll();
//Start adding elements..
tempPanel = new JPanel();
instPrincipal.panelPrincipal.add(tempPanel);
btnSave = new JButton("Save");
btnSave.addActionListener(this);
tempPanel.add(btnSave);
//End.
instPrincipal.panelPrincipal.repaint();
}
public void actionPerformed(ActionEvent event) {
instPrincipal = Principal.getInstance();
Object source = event.getSource();
if (source == btnSave) {
// modify local data, Database .. ; //work but need to be repainted on panelPrincipal
instPrincipal.panelPrincipal.repaint();//does not work
}
}
}
Update
To clarify the problem more, I have one single JPanel on a JFrame and there are different classes to fill it for multiple functionalities, I call their methods using JMenuItems on the main frame, these Classes implement ActionListener, passing the panel didn't work, and also the method I am trying here.
I thought about changing the design to use CardLayout, but it was very difficult.
You are calling Principal as a static reference, so how is it supposed to know what frame to repaint? You should pass the instance of the JFrame through the constructor of the subclass. Like so:
private SubClass subClassInst = new SubClass(this);
And create the constructor like this
private JFrame parent;
public SubClass(JFrame parent) { this.parent = parent; }
You can then use it like so
this.parent.repaint();

Java - Separate Listener Class throws NullPointerException

Apologize for the long post, but I wanted to be as detailed as possible so there's a better chance people understand what I'm trying to convey:
OK, so an overview of this problem is that I'm trying to make a program that simulates a cash register. (This is a "for-fun" project). The way I set it up is:
CashRegister: main class that starts the program, serves as the main window for everything.
public class CashRegister extends JFrame {
...
}
Other classes: serve as JPanels that provide the different components of the main CashRegister window. Example:
public class NorthPanel extends JPanel {
...
}
Then in the CashRegister class:
add(new NorthPanel(), BorderLayout.NORTH);
etc.
Basically, I have a JTextField in the NorthPanel class called priceField that holds the value of the price the user enters. I have a separate class (Keypad) that also extends JPanel and serves as the number keypad in the center of the main window. In CashRegister:
add(new NorthPanel(), BorderLayout.NORTH);
add(new Keypad()); // (default for BorderLayout is CENTER)
One of the problems I have run into is that I created one class, EventHandler, to serve as the listener class for the entire program because there are components in each JPanel class (NorthPanel and Keypad, for instance) that need to communicate with each other; the user presses a keypad button, the price field in the NorthPanel needs to know what key in the keypad was pressed.
I don't know if the problem comes from the fact that these components are coming from different classes and are therefore referenced differently, or what. All the classes are in the same directory, I'm using NetBeans and it's all part of the same package.
In my EventHandler class, I created several different constructors so as to be able to pass in all the components that need to communicate with each other from different classes. For example:
public class EventHandler implements ActionListener {
private JTextField priceField;
private JButton[][] keypad;
public EventHandler(JTextField priceField) {
this.priceField = priceField;
}
public EventHandler(JButton[][] keypad) {
this.keypad = keypad;
}
}
In my NorthPanel class, I instantiate priceField first, configure it (set the font, etc.) and say:
EventHandler e = new EventHandler(priceField);
in my attempt to pass the priceField through to my listener class.
Then in the Keypad class, I say:
EventHandler e = new EventHandler(keypad);
for(int i = 0; i < 4; i++) {
for(int j = 0; j < 3; j++) {
keypad[i][j].addActionListener(e);
}
}
Then in the EventHandler class, having passed through those variables:
public void actionPerformed(ActionEvent e) {
for(int i = 0; i < 4; i++) {
for(int j = 0; j < 3; j++) {
if(keypad[i][j] == e.getSource()) {
// call a custom method to append the numbers to the text field
}
}
}
}
It is at this point that I get a NullPointerException. I don't know why, but my guess is that it's because the listener objects are coming from different classes and using different constructors because I have to pass in different objects from each class that need to communicate with each other. I'm not 100% sure though. Is there a way to get around this or am I doing something completely wrong?
You should let the CashRegister handle all user input, as it is the main Frame of your application (it extends the JFrame). For the sub-panels, make a method, such as aKeyWasPressed( int keyCode ), that will be called from your frame, within the body of keyPressed method you override.
Also, set the JFrame to be focusable, and preferably make the other panels unfocusable setFocusable(false);
Here is a sample code of the CashRegister:
public class CashRegister extends JFrame implements KeyListener
{
private NorthPanel northPanel;
private Keypad keypad;
public CashRegister ()
{
this.setFocusable(true);
this.addKeyListener(this);
northPanel = new NorthPanel();
keypad = new Keypad();
/* Your code ... */
}
#Override
public void keyTyped(KeyEvent ke)
{
/*Do nothing*/
}
#Override
public void keyPressed(KeyEvent ke)
{
northPanel.aKeyWasPressed( ke.getKeyCode() );
keypad.aKeyWasPressed( ke.getKeyCode() );
}
#Override
public void keyReleased(KeyEvent ke)
{
/*Do nothing*/
}
}
Note: To distinguish which key was pressed, inside the aKeyWasPressed method from your panels, you can do:
private void aKeyWasPressed(int code)
{
if(code == KeyEvent.VK_A)
{
/*If its letter 'A', do this...*/
}
}
Again, there are many ways of doing it, but letting the Frame itself handle all user input is, in my opinion, the best pratice in most cases, mainly when dealing with multiple panels.

Creating an actionlistener from a method in another class

Hi well my code so far does something like this: Click a button, opens a combobox. I want to select an option on the ComboBox and depending on which option is picked i want to open another combobox using getSelectIndex().
Here are parts of my code which are relevant. I know I have to make the other comboboxes not visible or removed but at the moment I'm just trying to make a combobox appear. As you can see i have inserted the actionlistener for the button which works and opens the combobox.however when selecting a string in the combobox no event occurs. However when I run it, no comboboxes appear.
public class Work extends JFrame {
// variables for JPanel
private JPanel buttonPanel;
private JButton timeButton;
public Work()
{
setLayout(new BorderLayout());
buttonPanel = new JPanel();
buttonPanel.setBackground(Color.RED);
buttonPanel.setPreferredSize(new Dimension(400, 500));
add(buttonPanel,BorderLayout.WEST);
timeButton = new JButton("Time");
buttonPanel.add(timeButton);
buttontime clickTime = new buttontime(); // event created when time button is clicked
timeButton.addActionListener(clickTime);
Time timeObject = new Time();
timeObject.SelectTime();
buttontime2 selectDest = new buttontime2();
timeObject.getAirportBox().addActionListener(selectDest);
}
public class buttontime implements ActionListener { //creating actionlistener for clicking on timebutton to bring up a combobox
public void actionPerformed(ActionEvent clickTime) {
Time timeObject = new Time();
timeObject.SelectTime();
add(timeObject.getTimePanel(),BorderLayout.EAST);
timeObject.getTimePanel().setVisible(true);
timeObject.getTimePanel().revalidate() ;
timeObject.getAirportBox().setVisible(true);
}
}
public class buttontime2 implements ActionListener{
public void actionPerformed(ActionEvent selectDest) {
Time timeObject = new Time();
timeObject.SelectTime();
if(timeObject.getAirportBox().getSelectedIndex() == 1) {
timeObject.getEastMidBox().setVisible(true);
}
else if(timeObject.getAirportBox().getSelectedIndex() == 2) {
timeObject.getBirmBox().setVisible(true);
}
else if(timeObject.getAirportBox().getSelectedIndex() == 3) {
timeObject.getMancbox().setVisible(true);
}
else if(timeObject.getAirportBox().getSelectedIndex() == 4) {
timeObject.getHeathBox().setVisible(true);
}
}
}
public static void main (String args[]) {
events mainmenu = new events(); //object is created
mainmenu.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainmenu.setSize(800,500);
mainmenu.setVisible(true);
mainmenu.setLayout(new BorderLayout());
mainmenu.setTitle("Learning how to use GUI");
mainmenu.setBackground(Color.BLUE);
mainmenu.setResizable(false);
}
}
my other class TIME
import javax.swing.JOptionPane;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class Time
{
private JComboBox timeAirportbox;//comboboxes declared
private JComboBox eastMidbox;
private JComboBox mancBox;
private JComboBox heathBox;
private JComboBox birmBox;
private String[] airport = {"","EM", "Bham", "Manc", "Heath"};//array of airports declared
private String[] destination = {"","NY", "Cali", "FlO", "MIAMI", "Tokyo"};//array of destinations declared
private JPanel timePanel;
public void SelectTime() {
//combobox objects created
timePanel = new JPanel();
timePanel.setBackground(Color.BLUE);
timePanel.setPreferredSize(new Dimension(400, 400));
timeAirportbox = new JComboBox(airport);//array is inserted into the JComboBox
timePanel.add(timeAirportbox);
timeAirportbox.setVisible(false);
eastMidbox = new JComboBox(destination);
timePanel.add(eastMidbox);
eastMidbox.setVisible(false);
mancBox = new JComboBox(destination);
timePanel.add(mancBox);
mancBox.setVisible(false);
heathBox = new JComboBox(destination);
timePanel.add(heathBox);
heathBox.setVisible(false);
birmBox = new JComboBox(destination);
timePanel.add(birmBox);
birmBox.setVisible(false);
}
public JPanel getTimePanel() {
return timePanel;
}
public JComboBox getAirportBox() {
return timeAirportbox;
}
public JComboBox getEastMidBox() {
return eastMidbox;
}
public JComboBox getMancbox() {
return mancBox;
}
public JComboBox getHeathBox() {
return heathBox;
}
public JComboBox getBirmBox() {
return birmBox;
}
}
The Time object that is built in Work constructor is not used:
Time timeObject = new Time();
timeObject.SelectTime();
buttontime2 selectDest = new buttontime2();
timeObject.getAirportBox().addActionListener(selectDest);
As you are only applying the action listener selectedDest to the combobox of that timeObject, which is not used, then the listener will never be called.
You can do two things to make it work:
Move the code that creates the listener and assign it to the combox in the first listener buttontime
Create the Time object only once and store it as a member of your Work instance. As your listener is a non-static inner classes of the Work class, it will be able to use it instead of creating a new Time object.
Edit: I didn't see that in your second listener, you were AGAIN building a new Time object. This object is really a different one than the one you have created earlier, so modifying one will not affect the other. You really should create the Time object once and store it as a member variable of your Work class, and then use this object in your listeners instead of recreating it.
To be clear, do it like this:
public class Work extends JFrame {
// ...
private Time timeObject;
public Work() {
// ...
timeObject = new Time();
timeObject.SelectTime();
buttontime2 selectDest = new buttontime2();
timeObject.getAirportBox().addActionListener(selectDest);
}
public class buttontime implements ActionListener {
public void actionPerformed(ActionEvent clickTime) {
// use timeObject, don't create it and don't call SelectTime()
// example:
add(timeObject.getTimePanel(),BorderLayout.EAST);
// ....
}
}
public class buttontime2 implements ActionListener {
public void actionPerformed(ActionEvent clickTime) {
// use timeObject, don't create it and don't call SelectTime()
}
}
}
Also to note:
You should not extends JFrame, there is no reason to do so. Refactor your code so that your frame is just a member variable of your Work class.
Follow Java standard code conventions, especially use case properly with class names: buttonlistener should be ButtonListener, and method should start with lowercase: SelectTime should be selectTime.

ActionListener style - Good or bad [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I have a simple GUI which contains:
a push button.
Two radio buttons
Now I want to listen to each one of these buttons. What I do is something like that:
public class TestApp implements ActionListener {
private JFrame frame;
private JButton btn;
private JRadioButton rdb1;
private JRadioButton rdb2;
public static void main(String[] args) { /*....*/ }
private void initialize() {
//Each time I add a button, I add it to the listener:
btn = new JButton("Button");
btn.addActionListener(this);
//..
rdb1 = new JRadioButton("Value1");
rdb1.addActionListener(this);
//And so on...
}
//The ActionEvents
public void actionPerformed(ActionEvent e) {
if(e.getSource()==btn)
//...
if(e.getSource()==rdb1)
//...
}
}
Now I want to know if this considered a good/bad style?
Unless the listener is a very long method, I personally prefer the anonymous class pattern:
final JButton btn = new JButton("Button");
final JRadioButton rdb1 = new JRadioButton("Value1");
final ActionListener listener = new ActionListener() {
#Override
public void actionPerformed(final ActionEvent e) {
if (e.getSource() == btn) {
//...
} else if (e.getSource() == rdb1) {
//...
}
}
};
btn.addActionListener(listener);
rdb1.addActionListener(listener);
or even better:
btn.addActionListener(new ActionListener (){
public void actionPerformed(ActionEvent e) {
// btn handling code
}
});
rdb1.addActionListener(new ActionListener (){
public void actionPerformed(ActionEvent e) {
// rdb1 handling code
}
});
The pattern you are using allows other class to set the class TestApp to be set as a listener by other classes - unless this is intended, it is not a good practice.
A lot comes down to the complexity of what the action listener is trying to do. If you want small, single use actions, then an anonymous class would suitable.
The main benefit of using this style of listener is it will isolate exactly what the action is doing and who it's doing it for. The drawback comes when the listener contains more then, say, 10 or more lines, as it starts to becoming difficult to read and know where the listener actually ends.
In this case, something like a inner class might be more suitable. It has the benefit of an anonymous class (being tied to the class that uses it), but is easier to read.
If you want reusable actions (think of things like open, new, save), then you're better off using the Action API, which provides self configurability as well a self contained action listener
IMHO
More object-oriented way is to create an anonymous class for implementation of each of the listeners.
Creating only one listener that switches on the event source component is not very readable, but moreover, when the number of listeners increases, it becomes error prone. You can easily forget to handle all of the possible event sources in the switch block (or a chain of if-else blocks), which will result in a runtime exception silent wrong behaviour (nothing would happen for that case).
Adding individual listeners to each of the components will give you compile-time checking that you haven't forgotten to handle all of them.
public class TestApp {
// you can initialize fields inline to make thing shorter and safer
private JButton btn = new JButton("Button");
private JRadioButton rdb1 = new JRadioButton("Value1");
private void initialize() {
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// something
}
});
rdb1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// something else
}
});
}
}
Because the anonymous class syntax is very verbose, you can shorten the code of the initialize method by moving the listeners into private fields.
public class TestApp {
private JButton btn = new JButton("Button");
private JRadioButton rdb1 = new JRadioButton("Value1");
private void initialize() {
btn.addActionListener(btnListener);
rdb1.addActionListener(rb1Listener);
}
private final ActionListener btnListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// something
}
};
private final ActionListener rb1Listener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// something else
}
};
}
You can think about two other ideas:
Give each UI element its own Listener; they're completely independent that way.
Inject the Listeners into your Swing UI rather than calling new. You give users the opportunity to change the behavior as they see fit. Let your Swing UI do what it was meant to do: display results. That's it. I would argue that Listeners are part of the Controller logic.
It depends to a certain extent on what you want to do in the actionPerformed method. If no other class is likely to want to call this method then I may be tempted to reduce the scope of the actionPerformed method by creating an inner class e.g.:-
public class TestApp {
private JFrame frame;
private JButton btn;
private JRadioButton rdb1;
private JRadioButton rdb2;
private class CombinedActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if(e.getSource()==btn)
//...
if(e.getSource()==rdb1)
//...
}
}
public static void main(String[] args) { /*....*/ }
private void initialize() {
ActionListener listener = new CombinedActionListener()
//Each time I add a button, I add it to the listener:
btn = new JButton("Button");
btn.addActionListener(listener);
//..
rdb1 = new JRadioButton("Value1");
rdb1.addActionListener(listener);
//And so on...
}
}
You could even make the listener class a static inner class or a top-level class by passing the button instances into the constructor - which would make the listener class easier to test.
As I said above though, this is largely dependent on i) if anyone else is likely to call this method and ii) the complexity of the logic inside the method.

Categories