Java enter key the same as submit button? - java

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

Related

JAVA ActionListener for every button

im trying to make simple calculator in java GUI. I got to the point where I can clearly see that code is just ugly because of repeating functions like:
number0 = new JButton("0");
number0.setBounds(130, 280, 50, 50);
add(number0);
number0.addActionListener(new GetNumber0());
public class GetNumber0 implements ActionListener {
public void actionPerformed(ActionEvent e) {
String text =number0.getText();
int num = Integer.parseInt(text);
result=(result*10)+num; // +num if else than 0
lResult.setText("Result: "+result);
}
}
Which I'm doing for every button, so is there a way to make this code look better? I'm hoping for something that can get a variable from each button individually and use it in only one fucntion named GetNumber().
You don't need to create a separate listener, and you really shouldn't. It's not useful to write String text = number0.getText(); because you already know it's going to be 0.
Share the ActionListener between the buttons.
public class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
JButton btn = (JButton) e.getSource();
int num = Integer.parseInt(btn.getText());
result=(result*10)+num;
lResult.setText("Result: "+result);
}
}

I can't get the string from ActionListener to different class in Java

I created a JComboBox and JButton to submit information. I need the information to be sent to a different class to sort it out with a switch method. But it looks like the string created inside the ActionListener is not recognized by a different class.
public Main() {
final JComboBox comboB = new JComboBox(b); //add int b in here for array
comboB.setBounds(50, 30, 123, 20);
contentPane.add(comboB);
JButton btnTest = new JButton("Test");
btnTest.setBounds(300, 350, 89, 23);
contentPane.add(btnTest);
btnTest.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String s = (String)comboB.getSelectedItem();
}
});
}
How do I make it so that String s can be recognized by other classes? I have a separate class that will change action depending on what is selected from ComboBox, but I just can't seem to get this information out. Thank you.
Firstly, other objects need some way to register an ActionListener to the combo box. I would suggest providing a addActionListener method to your class, this would act as a proxy method and simple pass the call onto comboB
Secondly, this means comboB is going to need to be a class instance variable
Thirdly, the other classes are going to need to determine if the action originiated from the combo box or not, for example.
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() instanceof JComboBox) {
JComboBox cb = (JComboBox)e.getSource();
String s = (String)cb.getSelectedItem();
}
}
Now, there's not a lot of context available to the question, but, personally, I would normally either use a model of some kind that your UI class would update and/or a PropertyChangeListener that other classes could register against and monitor for changes to the "properties" of the your main class.
You just need to create a private method and have the combo call that. Then you just navigate to your component/class, and perform the action.
public Main() {
final JComboBox comboB = new JComboBox(b); //add int b in here for array
comboB.setBounds(50, 30, 123, 20);
contentPane.add(comboB);
JButton btnTest = new JButton("Test");
btnTest.setBounds(300, 350, 89, 23);
contentPane.add(btnTest);
btnTest.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String s = (String)comboB.getSelectedItem();
myMethodThatProcessesS(s);
}
});
}
private void myMethodThatProcessesS(String s) {
contentPane.getSomeOtherComponent().doSOmething(s);
}
Since java swing implements the MVC pattern you can pass the JComboBox's model reference to other objects.
Models implement the observer pattern and therefore the other objects can register themself if they need to get notified immediatly when the model changes.
public class Main {
public initializeComponent(OtherClass otherClass) {
...
JComboBox comboBox = ...;
ComboBoxModel comboBoxModel = comboBox.getModel();
otherClass.setComboBoxModel(comboBoxModel);
}
}
public class OtherClass {
private ComboBoxModel comboBoxModel;
public void setComboBoxModel(ComboBoxModel comboBoxModel) {
this.comboBoxModel = comboBoxModel;
ListDataListener listener = ...;
comboBoxModel.addListDataListener(listener);
}
public String getSelectedItem(){
Object selectedItem = comboBoxModel.getSelectedItem();
...
}
}

Common Action Listener for 3 Buttons

I am having trouble with the design of my code. I have 3 buttons not in a button group. I want to - based on the selected button - perform an action. Now the action requires a modification of an object in the class. This means i cannot use an inner class because this does not have access to the outer. If i could add an event listener to a button group this would be much easier but as i see it i will need an event handler for each radio button, is this correct? If not how else can i do it? Thanks
A quick example
public class Test(){
RadioButton 1 = new RadoButton();
RadioButton 2 = new RadoButton();
RadioButton 3 = new RadoButton();
Object myObject = new Object();
public void clickEvent(){
if(1.isSelected()){
myObject.doOne();
}else if(2.isSelected()){
myObject.doTwo();
}.....
}
}
You can set the same listener to all your buttons.
Pseudo code:
radioButton1 = new RadioButton();
radioButton2 = new RadioButton();
radioButton3 = new RadioButton();
listener = new ActionListener() {
...
}
radioButton1.addActionListener(listener);
radioButton2.addActionListener(listener);
radioButton3.addActionListener(listener);
This is to illustrate how you can use an inner class:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JRadioButton;
public class TestInnerClass {
JRadioButton radioOne = new JRadioButton();
JRadioButton radioTwo = new JRadioButton();
JRadioButton radioThree = new JRadioButton();
Object myObject = new Object();
public TestInnerClass() {
ActionListener myInnerClass = new MyActionListener();
radioOne.addActionListener(myInnerClass);
radioTwo.addActionListener(myInnerClass);
radioThree.addActionListener(myInnerClass);
}
private class MyActionListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent event) {
if(radioOne.isSelected()) myObject.toString();
else if(radioTwo.isSelected()) myObject.notify();
else if(radioThree.isSelected()) myObject.getClass().getName();
}
}
}
Note how the inner class is not static, as stated in gontard's comment, so does have visibility to myObject. And it's safest to keep it private.
It's often good to have one listener handle all events, as in this case. There are, however, other cases where you want your event handling more specific to each component. For example, in these cases, radioThree could trigger the event, and since these buttons are not in a group it might be possible that radioOne is still in the selected state. This single handler will fire and act only on the first radio. While one way to fix this would be to add checks for the source, as in:
public void actionPerformed(ActionEvent event) {
if(event.getSource() == radioOne && radioOne.isSelected())
myObject.toString();
if(event.getSource() == radioTwo && radioTwo.isSelected())
myObject.notify();
if(event.getSource() == radioThree && radioThree.isSelected())
myObject.getClass().getName();
}
Another way would be to use one listener for each component. That's where the anonymous class comes in very handy:
radioOne.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
myObject.doOne();
}
});
One of my favorite patterns, especially if the work is non-trivial, is to first create a method to do the work, then call it from the listener. I also wrap the call in SwingUtilities.invokeLater() to get the work off the Swing Event Thread.
public class Test {
JRadioButton radioOne = new JRadioButton();
Object myObject = new Object();
private void handleRadioOne() {
myObject.toString();
// etc, etc.
}
public Test() {
radioOne.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
handleRadioOne();
}
});
}
});
}
}
This provides two nice features:
It encapsulates your action work into a method allowing for programmatic access if later desired
It ensures that the method's work stays off the Swing Event Thread, so your GUI won't hang up during intensive processing

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.

action listener in another class - 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());

Categories