• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Organizing ActionListeners

 
Ranch Hand
Posts: 377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I have buttons in separate classes that will use the exact same code for an action. I've been reading about nested classes but I'm not sure that is the best approach. What is the preferred method for logically separating actionlisteners in the code and instantiating them for different buttons? TIA.
 
Marshal
Posts: 79177
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
We usually discuss this sort of thing in our GUIs forum; this thread will eventually migrate thither.

I have a rule of thumb about Listeners:-
  • 1: If a Listener does something generic which might be useful elsewhere: public top‑level class. I couldn't find such a top‑level class, but I did find this, which you can doubtless complete easily enough. No, I have found a more complete version here, but it appears only to work on 1st April.
  • 2: If a Listener is used several times for similar things, make it a private inner class.
  • 3: If it is used in one place and nowhere else and there is nothing else similar, I would in the past have said use an anonymous class.
  • Of course nowadays in Java8 you can often use a λ expression instead:-If you look at the ActionListener interface, you find it is a functional interface; even though it is not annotated with @FunctionalInterface, ActionListener has only one abstract method (in fact it only has one method at all), so it counts as a functional interface. That means the compiler can create an instance without needing the whole class written out. You need the method parameters, the arrow token, and the method body, and the javac tool can work out what to do:-can be shortened by leaving out the method name and replacing the {} with ->Now the compiler can usually infer the type of the parameter, so you can omit that.If you only have one token in the () left of ->, you can miss out the ()Now you have reduced about ten lines of code to that.
    Similarly you can often replace an anonymous class by a λ:-Read about inner classes in the Java™ Tutorials.
     
    Dennis Putnam
    Ranch Hand
    Posts: 377
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Thanks for the replies. Unfortunately I am not really following those examples, at least as to how it relates to what I am asking. I think I am asking to put all the various reusable listeners in a class (file) and then be able to instantiate them where needed. What I envisioned was something like this.

    filename=Listeners.java


    filename=someother.java

    Then use the similar code in other classes/files to instantiate other SaveButtonListeners.
     
    Marshal
    Posts: 28193
    95
    Eclipse IDE Firefox Browser MySQL Database
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    The important part of Campbell's reply is that you don't have to write named subclasses of ActionListener. You just need code like this:



    and then you can use that variable anywhere you like. But that's already in his post so I won't repeat it.

    You could certainly put all of those variables in some other Java class if you liked. But I wouldn't do that. Most of the ActionListeners I have written are designed to do something to the GUI, or at least the data behind it. If you put such an ActionListener in a different class then you're going to have to figure out how it can access that data. Besides, a designer should ask "What is the purpose of an object of this class?" If the answer is that its purpose is to be an ActionListener, well, why aren't you having a class where you store all your Strings or all your integers? It would make more sense to declare the shared ActionListeners in the same class as the shared JTextFields or whatever. (Notice that you didn't propose a separate class to store all references to JTextFields.)
     
    Campbell Ritchie
    Marshal
    Posts: 79177
    377
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    ...And those listeners in the other .java file are awkward to access. You would have to write
    new Listeners().new SaveButtonListener()
    I am afraid your simplest solution is to go back and rewrite your listeners. Most Listeners are of local applicability only, so use the syntax I showed you, or inner classes if you are not using Java8.
    By all means create a button factory class, but it will be completely different from your current class. It will be a utility class:-
  • 1: Private constructor only to prevent instantiation (and subclassing).
  • 2: No variables.
  • 3: All fields (final only) and methods are static.
  • All the methods of that class would create a button, using whatever information is given. You can pass listener references as appropriate.
     
    Dennis Putnam
    Ranch Hand
    Posts: 377
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Thanks again. I think I am beginning to see.
     
    Paul Clapham
    Marshal
    Posts: 28193
    95
    Eclipse IDE Firefox Browser MySQL Database
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    To put it a different way: You probably have the initialization of your GUI all in one place, I expect? Well, the ActionListeners are part of the GUI, usually, so they should be initialized -- and declared -- in that same place.
     
    Saloon Keeper
    Posts: 15510
    363
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    I put this reply in another one of your topics, but it seems it's more fitting here.

    I prefer to use Actions, because you can do some really cool stuff with them (reuse them for menu items, toolbar buttons, other buttons; disable them; rename them everywhere instantly, etc.).

    Here is a complete example that shows actions in action (hehehe). The example uses a utility class that makes it easy to create new actions using lambda expressions:




    You can see that in the above example, I use one Action to instantiate both a JMenuItem and a JButton, and when I disable the action, both of these buttons are disabled as well. Actions make it very easy to manage complex looking scenarios in large GUIs.
     
    reply
      Bookmark Topic Watch Topic
    • New Topic