Passing to listener - java

Is it possible to pass a String to an ActionListener? I'm creating a number guessing game, and I need to pass the difficulty selected to the the ActionListener, because it's passed from the first GUI opened. How would I do this as it's passed directly to the Game() constructor?

Have your ActionListener access a variable that contains the result of the guess.
I would do something like:
final JTextArea textArea = new JTextArea();
JButton button =new JButton("press");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
String text = textArea.getText();
if (text.equals("something")) {
doSomething();
} else {
doSomethingElse();
}
}
});

Where does the string come from? You can pass that component to the ActionListener when constructed. For example, your string comes from a JLabel object. Then
class GuessNumberActionListener implements ActionListener {
private JLabel difficulty;
public GuessNumberActionListener(JLabel difficulty) {
this.difficulty = difficulty;
}
// implement other methods
}
Then inside your action listener, you can access/update what you want.

ActionListener is an interface. try extending the functionality of the interface using inheritance. this will do the trick

Sure you can. There are lots of ways but one of them is to pass it in to the the ActionListener's constructor:
public class MyClass implements ActionListener {
private int difficultyLevel;
public MyClass(int difficultyLevel) {
this.difficultyLevel = difficultyLevel;
}
public void actionPerformed(ActionEvent e) {
...//code that reacts to action and does something based on difficultyLevel
}
}
UPDATE:
Looks like the design patterns police are out in full force today. You may want to quickly rewrite your app in MVC before you get shot in the foot :)
http://java.sun.com/products/jfc/tsc/articles/architecture/

Related

Define and ActionListener in class which extends Button

How to place Action Listener directly in definition of class that extends Button ?
If object of class Button is created then we could simply use anonumous inner class :
b = new Button("Click me");
b.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent e){
System.out.println("stringToPrint");
}
}
);
how to do the same in below :
class CustomizedButton extends Button{
String customClass;
Button(String stringToPrint){
super(customClass); //customClass is also button name
this customString = stringToPrint;
}
/*this.addActionListener( //don't work this way
new ActionListener(){
public void actionPerformed(ActionEvent e){
System.out.println(customClass);//use outer(?) field
}
}
);*/
}
I need to create 20 almost identical but slightly different buttons, so anonymous inner is too long
You could declare a private nested class, like so:
public class CustomizedButton extends Button{
String customClass;
CustomizedButton(String stringToPrint){
super(customClass); //customClass is also button name
this.customString = stringToPrint;
addActionListener(new MyListener());
}
private class MyListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// TODO: listener code here
}
}
}
But it's not much different from using an anonymous inner class or lambda:
public class CustomizedButton extends Button{
String customClass;
CustomizedButton(String stringToPrint){
super(customClass); //customClass is also button name
this.customString = stringToPrint;
addActionListener(e -> myListenerCode(e));
}
private void myListenerCode(ActionEvent e) {
// TODO: listener code here
}
}
Having said this, other issues come to mind:
Usually it's best to favor composition over inheritance. I would bet that what you really want is some sort of factory method that creates your button complete with listener
Why use AWT components such as the java.awt.Button class when it is 20+ yrs out of date? Why not Swing JButtons instead?
If you were using Swing JButtons, best would be to create a custom Action rather than extend JButton. Actions can hold and change many button properties, including a listener, the displayed text, icons, the tool tip text (displayed on hover)....
For that matter, you should favor JavaFX if this is a new project, since this is the current best-supported Java GUI library.
For example an AbstractAction class could look something like:
public class CustomizedAction extends AbstractAction{
String text;
CustomizedAction(String text, int mnemonic){
super(text); //text is also button name
this.text = text;
putValue(MNEMONIC_KEY, mnemonic); // for alt-key short cut if desired
}
#Override
public void actionPerformed(ActionEvent e) {
String currentName = getValue(NAME); // same value as the text field
System.out.println(currentName);
// TODO: more listener code here
}
}
and could be used like so:
JButton button = new JButton(new CustomizedAction("Foo", KeyEvent.VK_F));

Getting the value of TextField from one class to another with button

I'm working on getting the value of a textfield from another class using Vaadin.
my solution is something like this.
public class MyTextField{
String str;
public MyTextField(){
TextField text = new TextField();
str = text.getValue().toString();
}
public String getStr(){
return str;
}
}
public class MyButton{
public MyButton(){
Button button = new Button("UPDATE");
button.addListener(new Button.ClickListener(){
#Override
public void buttonClick(ClickEvent event) {
MyTextField text = new MyTextField();
System.out.println(text.getStr());
}
});
}
}
the problem is, I always get null result. any help is highly appreciated. Thank you.
In all likelihood the MyTextField object inside of your buttonClick method is not the same MyTextField that is being displayed to the user. A solution is to get a reference to the class that holds the displayed MyTextField, and then call a public method on that reference to extract the text.
Edit 1
Note that I'm not familiar with Vaadin, but your MyTextField class looks suspicious in that you're declaring the TextField inside of the constructor making it visible only in the constructor. I'm also not sure what calling getValue() on it immediately and before any event, before the user's had a chance to interact with the component, will do. This looks very suspicious to me.
Edit 2
For instance, if this were Swing, I'd do something like:
public class MyTextField{
TextField textField = new TextField();
public MyTextField(){
}
// so it can be added to the gui
public TextField getTextField() {
return textField;
}
public String getStr(){
return textField.getValue().toString(); // not sure if this is correct
}
}
public class MyButton{
private MyTextField textField;
private Button button = new Button("UPDATE");
public MyButton(final MyTextField textField){
this.textField = textField;
button.addListener(new Button.ClickListener(){
#Override
public void buttonClick(ClickEvent event) {
System.out.println(textField.getStr());
}
});
}
}
Edit 3
You ask:
you have declared "private MyTextField textfield" as a field and add a parameter (MyTextField textfield) from the MyButton constructor. does it mean that I have to pass the class MyTextField to the MyButton class as a reference?
Again, note that I am not familiar with Vaadin, but I am familiar with general use of Java objects, and this I know. If you want to have one class (here MyButton) get the state of another object (here MyTextField), then the first object needs a valid reference to the second. One way to get this reference is by passing it in as a constructor parameter. Another is via a setter method, say by giving MyButton a setMyTextField(TextField textField) method, and then assigning the reference to your field. Another option is via "dependency injection", but I think that this may be a little too advanced for now, but do consider it in the future.
If you try to do it as you're doing it in your original post, things will likely fail, since sure, you're giving MyButton a MyTextField object, but what MyTextField object is this? It's one that has been created in the MyButton class and is present no where else.
I would rather do some thing like this, to achieve what you are doing. This is based on the assumption that you are trying to read the user entered value on click of a button.
There are two option to achieve this.
Option 1
public class MyTextField extends TextField{
public MyTextField(){
}
public String getStr(){
return this.getValue();
}
}
public class MyButton extends Button{
public MyButton(){
setCaption("UPDATE");
}
}
//Add in your presentation logic
final MyTextField text = new MyTextField();
MyButton button = new MyButton();
mainLayout.addComponent(text);
mainLayout.addComponent(button);
button.addClickListener(new ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
System.out.println(text.getStr());
}
});
Option 2
public class MyTextField extends TextField{
public MyTextField(){
}
public String getStr(){
return this.getValue();
}
}
public class MyButton extends Button{
public MyButton(final MyTextField text){
setCaption("UPDATE");
addClickListener(new ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
System.out.println(text.getStr());
}
});
}
}
//And in your presentation logic
final MyTextField text = new MyTextField();
MyButton button = new MyButton(text);
mainLayout.addComponent(text);
mainLayout.addComponent(button);
Please let me know if in case if this is not what you are expecting.
And Kudos to Hovercraft Full Of Eels for trying to help him out
Thanks.

JPanel Action Listener

I have a JPanel with a bunch of different check boxes and text fields, I have a button that's disabled, and needs to be enabled when specific configurations are setup.
What I need is a listener on the the whole JPanel looking for events, whenever anything changes.
I believe I need an action listener but I can't find anything to bridge the action Listener with the JPanel
JPanel Window = new JPanel();
Window.addActionListener(new ActionListener(){
//Check if configurations is good
}
I figure I can copy and paste my code a bunch of times into every listener in the panel, but that seems like bad coding practice to me.
First off as #Sage mention in his comment a JPanel is rather a container than a component which do action. So you can't attach an ActionListener to a JPanel.
I figure I can copy and paste my code a bunch of times into every
listener in the panel, but that seems like bad coding practice to me.
You're totally right about that, it's not a good practice at all (see DRY principle). Instead of that you can define just a single ActionListener and attach it to your JCheckBoxes like this:
final JCheckBox check1 = new JCheckBox("Check1");
final JCheckBox check2 = new JCheckBox("Check2");
final JCheckBox check3 = new JCheckBox("Check3");
final JButton buttonToBeEnabled = new JButton("Submit");
buttonToBeEnabled.setEnabled(false);
ActionListener actionListener = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
boolean enable = check1.isSelected() && check3.isSelected();
buttonToBeEnabled.setEnabled(enable);
}
};
check1.addActionListener(actionListener);
check2.addActionListener(actionListener);
check3.addActionListener(actionListener);
This means: if check1 and check3 are both selected, then the button must be enabled, otherwise must be disabled. Of course only you know what combination of check boxes should be selected in order to set the button enabled.
Take a look to How to Use Buttons, Check Boxes, and Radio Buttons tutorial.
A suggestion could be to derive a class from each of the components you're using and add an ActionListener that bubbles up the Container tree and looks for the first Container that implements a custom interface like this:
public interface MyCommandProcessor {
void execute(String actionCommand);
}
public class MyButton extends JButton {
public MyButton(string actionCommand) {
setActionCommand(actionCommand);
addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
Container traverser = MyButton.this;
while (traverser != null && !(traverser instanceof MyCommandProcessor))
traverser = traverser.getParent();
if (traverser != null)
((CommandListener)traverser).execute(ae.getActionCommand());
}
});
}
}
public class MyApp extends JFrame implements MyCommandListener {
public MyApp() {
JPanel panel = new Panel();
panel.add(new MyButton("MyButton got pressed"));
}
public void execute(String actionCommand) {
System.out.println(actionCommand);
}
}
You need to create custom component listener. Look here:
Create a custom event in Java
Creating Custom Listeners In Java
http://www.javaworld.com/article/2077333/core-java/mr-happy-object-teaches-custom-events.html
I do it throw the standard ActionListener
Example
public class MyPanel extends JPanel {
private final JComboBox<String> combo1;
private final JButton btn2;
.......
//catch the actions of inside components
btn2.addActionListener(new MyPanelComponentsActionListener());
........
//assign actionlistener to panel class
public void addActionListener(ActionListener l) {
listenerList.add(ActionListener.class, l);
}
public void removeActionListener(ActionListener l) {
listenerList.remove(ActionListener.class, l);
}
//handle registered listeners from components used MyPanel class
protected void fireActionPerformed(ActionEvent event) {
// Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();
ActionEvent e = null;
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==ActionListener.class) {
// Lazily create the event:
if (e == null) {
String actionCommand = event.getActionCommand();
if(actionCommand == null) {
actionCommand = "FontChanged";
}
e = new ActionEvent(FontChooserPanel.this,
ActionEvent.ACTION_PERFORMED,
actionCommand,
event.getWhen(),
event.getModifiers());
}
// here registered listener executing
((ActionListener)listeners[i+1]).actionPerformed(e);
}
}
}
//!!! here your event generator
class MyPanelComponentsActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
//do something usefull
//.....
fireActionPerformed(e);
}
}
....
}

Disable a JButton from a listener that's in a separate class

I'm writing a pretty big class and don't want to post it here. The question is the following, how do I refer to the button that was pressed in the constructor of a different class? Let's say, I want to disable it after some actions in the listener. If the listener were anonymus or were an inner class of the SomeClass, I would just use the name of the variable like this:
button.setEnabled(false);
But how can I do it when my listener is a separate class? Tried using e.getModifiers().setEnabled(false) and e.getSource().setEnabled(false), didn't work.
public class SomeClass extends JPanel {
private JButton button = new JButton("Button");
public SomeClass() {
button.setActionCommand("button");
button.addActionListener(new ButtonListener());
}
public static void main(String[] args) {
// TODO code application logic here
}
}
class ButtonListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
String src = e.getActionCommand();
if (src.equals("button")) {
//some actions here
//then
}
}
}
Try this ((JButton)e.getSource()).setEnabled(false)
It must work)
e.getSource() return component to which this event refers( docs)

Java Individual ActionListeners and an Overarching ActionListener

Perhaps I am going about this the wrong way. Let me know
Using Swing and AWT, I have several buttons set up on a frame and they each have an ActionListener corresponding to their specific function I.E.
JButton foo_button = new JButton("Foo-Me");
foo_button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//Fancy schmancy code work
}
})
JButton bar_button = new JButton("Bar None");
bar_button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//Fancy schmancy code work
}
})
So each of these buttons do their own thing. However, what if I want all the buttons to do a certain thing (the same exact method for each), in my case, clear a label, before they do their own thing.
Obviously I could add whatever_label.setText("") to each actionPerformed() but that entails a lot of duplication, something I'm not so much a fan of.
Oh Java and Swing gurus come to my aid.
You can subclass your own implementation of ActionListener:
private static abstract class MyListener implements ActionListener {
#Override
final public void actionPerformed(ActionEvent evt) {
theSameTask();
uniqueTask(evt);
}
private void theSameTask() {
// the identical task
}
public abstract void uniqueTask(ActionEvent evt);
}
And then, the new listeners will look like this:
JButton bar_button = new JButton("Bar None");
bar_button.addActionListener(new MyListener() {
#Override public void uniqueTask(ActionEvent evt) {
//Fancy schmancy code work
}
});
Another possibility is to use the 'Decorater' pattern, and write an ActionListener decorator for the common behavior. Your code would then be of the form
bar_button.addActionListener(new MyActionListenerDecorator( new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//Fancy schmancy code work
} }) );
I think the best way to do this is to use Action. That way all the listeners always do the same thing.

Categories

Resources