Swing JButton event - java

I have JButton and want on event call this class method show() when this button in pressed. I know how to this, if I want use method from another class, but I need call method from same class as button.
JButton search = new JButton(new ButtonAction("Search", KeyEvent.VK_A));
I try add
JButton search = new JButton(show());
But it works only 1 time when object creating, but not when button is pressed.

Not sure what you want here... but if you want to attach an actionListener() to a JButton, you can do the following. Why do you need to listen to A?
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ActionListenerExample1 extends JFrame
implements ActionListener, KeyListener {
private static final long serialVersionUID = 1L;
private JTextField searchText;
private JButton searchButton1;
private JButton searchButton2;
public ActionListenerExample1() {
initialize();
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
protected void initialize() {
searchText = new JTextField(30);
searchButton1 = new JButton("Search 1");
searchButton2 = new JButton("Search 2");
searchText.addKeyListener(this);
searchButton1.addActionListener(this);
searchButton2.addActionListener(new ButtonAction());
this.setLayout(new FlowLayout());
this.add(searchText);
this.add(searchButton1);
this.add(searchButton2);
}
public static void main(String[] args) {
new ActionListenerExample1();
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == searchButton1) {
buttonAction("GLOBAL LISTENER");
}
}
private class ButtonAction implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
buttonAction("LOCAL LISTENER");
}
}
private void buttonAction(String label) {
JOptionPane.showMessageDialog(this,
String.format("%s: %s", label, searchText.getText()));
}
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyChar() == KeyEvent.VK_A) {
buttonAction("KEYBOARD");
}
}
#Override
public void keyReleased(KeyEvent e) { }
#Override
public void keyTyped(KeyEvent e) { }
}

If I understand you correctly, you want to call a method from the class that you created the button in rather than a method from another class.
First off, notice that while you are technically calling a method here
JButton search = new JButton(new ButtonAction("Search", KeyEvent.VK_A));
what is really going on is that you are passing a ButtonAction object to the JButton constructor. The closest thing that I can think of that will get what you want is having the class you are using extend ButtonAction.

Related

Clicking a JButton from keyboard using KeyListener

Like I described in the title, I am required to make a JButton clicked if a key from a keyboard is pressed. For example :
ActionListenerClass actionListener = new ActionListenerClass();
KeyListenerClass actionListener = new KeyListenerClass();
JButton aButton = new JButton("A");
aButton.setActionCommand("A");
aButton.addActionListener(actionListener);
aButton.addKeyListener(keyListener);
When "A" is pressed from the keyboard, button A will perform a doClick() and send the action command to a private class of the action listener for event handling. Now I have read a lot of solution from stack overflow, and they all used key binding, which is to bind between an input map and an action map. The thing is I absolutely have to use a key listener with a private class but not the binding. The only thing I can guess now is the keyListener above have to somehow receive the keyboard input and perform doClick on the button it is binded to in a keyPressed method, which I have try and it didn't work at all.
Edit: Here's my entire code.
CalculatorViewController.java
import java.awt.*;
import java.awt.event.*;
import java.util.regex.Pattern;
import javax.swing.*;
/**Create the app GUI
* #author Bach Le
* #version 1.0
* #see java.awt, java.awt.event, javax.swing
* #since 12.0.1
*/
public class CalculatorViewController extends JPanel {
private JButton backSpaceButton;
public CalculatorViewController() {
Controller controller = new Controller();
KeyController keyController = new KeyController();
setBorder(BorderFactory.createMatteBorder(5, 5, 5, 5,Color.black));//Adding the panel border
backSpaceButton = new JButton("\u21DA");
backSpaceButton.setPreferredSize(new Dimension(52,55));
backSpaceButton.setOpaque(false);//set transparency
backSpaceButton.setContentAreaFilled(false);
backSpaceButton.setBorderPainted(false);
backSpaceButton.setActionCommand("Backspace Button");//set the action command
backSpaceButton.addActionListener(controller);//add action listener
backSpaceButton.setToolTipText("Backspace (Alt+B)");//set tooltip text
backSpaceButton.setFont(font);//set the font
backSpaceButton.addKeyListener(keyController);
add(backSpaceButton) ;
}
private class Controller implements ActionListener{
public void actionPerformed(ActionEvent e) {
//event handling here
}
}
private class KeyController implements KeyListener{
#Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==65) {
backSpaceButton.doClick();
}
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
}
}
2.Calculator.java
public class Calculator {
public static void main(String[] args) {
CalculatorViewController pane = new CalculatorViewController();
JFrame frame = new JFrame("Calculator");
frame.setContentPane(pane);
frame.setSize(380, 520);
frame.setLocationByPlatform(true);
frame.setResizable(true);
frame.setVisible(true);
}
}
Focus on CalculatorViewController, I am trying to make backSpaceButton clicked when A is pressed (Of course it is the actual backspace button but I will fix it later), so it will send its action command to the action listener registered to it, which will be processed in the method of Controller inner class. I am not sure the proper way to achieve this.
Adding a KeyListener will only work for components with focus. You would not want to add the KeyListener to the JButtons, because only one JButton will be in focus.
For just setting a value you could use setMnemonic but then you would have to use a modifier (such as 'alt) when you press the key.
The 'correct' way to do this is to use key bindings
Here is an example with two buttons.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class ButtonKeys{
public void buildGui(){
JFrame frame = new JFrame("key buttons");
JPanel panel = new JPanel(new BorderLayout());
JButton a = new JButton("A");
a.addActionListener(evt->{ System.out.println("a pressed");});
JButton b = new JButton("B");
b.addActionListener(evt->{ System.out.println("b pressed");});
panel.add(a, BorderLayout.EAST);
panel.add(b, BorderLayout.WEST);
frame.setContentPane(panel);
frame.setVisible(true);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
KeyStroke us = KeyStroke.getKeyStroke(KeyEvent.VK_A, 0, false);
panel.getInputMap().put(us, "A");
panel.getActionMap().put("A", new AbstractAction(){
#Override
public void actionPerformed(ActionEvent evt){
a.doClick();
}
});
KeyStroke us2 = KeyStroke.getKeyStroke(KeyEvent.VK_B, 0, false);
panel.getInputMap().put(us2, "B");
panel.getActionMap().put("B", new AbstractAction(){
#Override
public void actionPerformed(ActionEvent evt){
b.doClick();
}
});
a.setFocusable(false);
b.setFocusable(false);
}
public static void main(String[] args){
EventQueue.invokeLater( new ButtonKeys()::buildGui);
}
}
I made the buttons to not obtain focus because if they get focus then their input map will be used.
This code should work for you. For the KeyListener I used a KeyAdapter more here as it is more convenient if you simply need to use one of the methods. You can of course move the Listeners to separate own classes if needed, but the behavior would stay the same.
public static void main(String[] args) {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
JButton btn = new JButton("A");
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Button clicked");
}
});
btn.addKeyListener(new KeyAdapter() {
public void keyTyped(KeyEvent e) {
if (e.getKeyChar() == 'A' || e.getKeyChar() == 'a') {
((JButton) e.getSource()).doClick();
}
}
});
panel.add(btn);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(0, 0, 800, 600);
frame.getContentPane().add(panel);
frame.setVisible(true);
}
If you really need to use a KeyListener, it would look like this:
btn.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
if (e.getKeyChar() == 'A' || e.getKeyChar() == 'a') {
((JButton) e.getSource()).doClick();
}
}
#Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
}
});

Why won't my .isSelected() method work?

Well what i'm trying to do is change the text of the JRadioButton's when they're selected, i got them to change the color. I know I can do it by putting the code to change the text inside the dedicated event handling method specific to each button, but how do I do it so that I use A DIFFERENT event handling method that just changes the buttons? I already created one but it doesn't work, here's the code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class LessonTwenty extends JFrame implements ActionListener{
JRadioButton b1,b2;
JTextArea t1;
JScrollPane s1;
JPanel jp = new JPanel();
public LessonTwenty()
{
b1= new JRadioButton("green");
b1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
jp.setBackground(Color.GREEN);
}
});
b2= new JRadioButton("red");
b2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
jp.setBackground(Color.RED);
}
});
//Method to change the text of the JRadion Buttons, what i'm trying to make work
new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(b1.isSelected()){
b1.setText("Welcome");
}
else if(b2.isSelected()){
b2.setText("Hello");
}
}
};
jp.add(b1);
jp.add(b2);
this.add(jp);
setTitle("Card");
setSize(700,500);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}
public static void main(String [ ] args){
new LessonTwenty();
}
#Override
public void actionPerformed(ActionEvent e) {
}
}
if i understand you right, you want do do something like this:
//Method to change the text of the JRadion Buttons, what i'm trying to make work
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(b1.isSelected()){
b1.setText("Welcome");
}
else if(b2.isSelected()){
b2.setText("Hello");
}
}
};
b1= new JRadioButton("green");
b1.addActionListener(al);
b2= new JRadioButton("red");
b2.addActionListener(al);
ie. you define one ActionListener which you use in all your objects.
The anonymous object you define in your original code does absolutely nothing, it just creates an ActionListener which nobody can ever access, since it is not assigned to any Button.
Maybe this could help
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(e.getSource() == b1){
b1.setText("Welcome");
} else if(e.getSource() == b2){
b2.setText("Hello");
}
}
};

How do I remove a button in one class/component using the actionPerformed method of another class?

In the code I am designing, I have a JButton instantiated in the main JFrame of my application that is using an ActionListener referencing an actionPerformed method in another class/component. I'm wondering if there is a way to remove that button upon running said actionPerformed method (clicking on it). In other words, is it possible for the actionPerformed method to reference back to the button that is activating it?
Can you get a reference to the object that caused the ActionListener to activate? Yes via the ActionEvent parameter's getSource() method.
i.e.,
public void actionPerformed(ActionEvent evt) {
Object theSource = evt.getSource();
}
A warning though: if you use this ActionListener or Action in multiple settings, such as with menus, the source may not be a button at all.
As far as using this to "remove" the button, you would then need to get the component's container, something like:
public void actionPerformed(ActionEvent evt) {
JButton button = (JButton) evt.getSource(); // danger when casting!
Container parent = button.getParent();
parent.remove(button);
parent.revalidate();
parent.repaint();
}
but again, I have to warn that you'll be in trouble if the event was not caused by a JButton, or if the layout manager that the parent uses doesn't things being removed. I have to wonder if a CardLayout would be better to use here.
e.g.,
import java.awt.Container;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class RemoveButton extends JPanel {
private static final long serialVersionUID = 1L;
private static final int BUTTON_COUNT = 5;
private Action removeMeAction = new RemoveMeAction("Remove Me");
public RemoveButton() {
for (int i = 0; i < BUTTON_COUNT; i++) {
add(new JButton(removeMeAction));
}
}
private static void createAndShowGui() {
RemoveButton mainPanel = new RemoveButton();
JFrame frame = new JFrame("Remove Buttons");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class RemoveMeAction extends AbstractAction {
private static final long serialVersionUID = 1L;
public RemoveMeAction(String name) {
super(name); // to set button's text and actionCommand
}
#Override
public void actionPerformed(ActionEvent evt) {
Object source = evt.getSource();
// AbstractButton is the parent class of JButton and others
if (source instanceof AbstractButton) {
AbstractButton button = (AbstractButton) source;
Container parent = button.getParent();
parent.remove(button);
parent.revalidate();
parent.repaint();
}
}
}

How to determine the event source in an ActionListener?

Ok. I'm not sure about the title of my question and whether I used the right words.
As I am a self taught total amateur I'm finding it hard to ask my question as I don't know the correct terms for things so I will write something in code and then ask my question. I've written it without import statements, setting up layouts and scrollbars and some other things just to keep it simpler.
public class Foo{
JTextArea text;
public static void main(String[] args){
Foo foo = new Foo;
foo.go();
}
public void go(){
JFrame frame = new JFrame();
JButton button = new JButton("One");
JButton button2 = new JButton("Two");
JPanel panel = new JPanel();
frame.setVisible(true);
frame.setSize(600, 300);
frame.getContentPane().add(BorderLayout.EAST, panel);
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.add(button);
panel.add(button2);
text = new JTextArea(10, 20);
panel.add(text);
button.addActionListener(new ButtLis());
button2.addActionListener(new ButtLis());
}
class ButtLis implements ActionListener{
#override
// this is where I have the problem
text.append();
}
}
What I want is an if statement to go into my inner class (ButtLis) which will determine which of the buttons are pressed and then append certain text to the JTextArea based on that. But I don't know what to call to find out which button was pressed.
You have a couple options. In the current case you have, where the JButton objects are locally scoped within the constructor, you would need to check for actionCommmand because the objects are not accessible from the ActionListener with their current scope. So you could do this
class ButtLis implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if ("One".equals(command)) {
// do something
}
}
}
If you wanted to compare object source, you would need to give your buttons a global scope
public class Foo {
JButton button = new JButton("One");
JButton button2 = new JButton("Two");
class ButtLis implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == button) {
}
}
}
}
A third option is to register the buttons individually
public void go() {
...
button.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
// do something
}
});
}
See more at How to use Common Button and How to Write ActionListeners
I think this is what you're looking for, although I would hardly recommend it:
class ButtLis implements ActionListener {
private JTextArea text;
public ButtLis(JTextArea text) {
this.text = text;
}
#Override
public void actionPerformed(ActionEvent e) {
JButton button = (JButton)e.getSource(); // Warning! This is not good coding practice, because you don't know that the source will be a button
text.append(button.getText());
}
}
Instead, I'd recommend:
JButton button1 = new JButton("One");
button1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
text.append("one");
}
});
That uses an "anonymous inner class" to define the action listener. For Button2, you'd say a similar thing. The benefits here are that the action listener is right next to the button that it works on, and it prevents you from having a single ActionListener that has to check where each event came from (using e.getSource()).
Inside your ButtLis, add this
class ButtLis implements ActionListener {
public void actionPerformed(ActionEvent e) {
e.getSource();
//Your implementation
}
}
Here the class that implements ActionListener:
class ButtLis implements ActionListener {
JTextArea text;
public ButtLis(JTextArea text) {
this.text = text;
}
#Override
public void actionPerformed(ActionEvent ae) {
if (ae.getSource() instanceof JButton) {
JButton button = (JButton) ae.getSource();
if(text != null){
text.append(" " + button.getText());
}
}
}
}
And here how to add an action listener to the buttons:
button.addActionListener(new ButtLis(text));
button2.addActionListener(new ButtLis(text));
For a generale ActionListsner, i suggest a different customer ActionListener like this:
abstract class ButtLis implements ActionListener {
protected String sourceEvent; //or you can use a reference for the source object
public ButtLis(String sourceEvent) {
this.sourceEvent = sourceEvent;
}
public String getSourceEvent() {
return sourceEvent;
}
#Override
public void actionPerformed(ActionEvent ae) {
customer_actionPerformed(ae);
}
public abstract void customer_actionPerformed(ActionEvent ae);
}
And the adding of action listener for any component is the same as an ordinary ActionListener:
//for exemple button
button.addActionListener(new ButtLis(button.getText()) {
#Override
public void customer_actionPerformed(ActionEvent ae) {
text.append(getSourceEvent());
}
});

ActionAdapter cannot be resolved to a type

I've started learning about event handlers and have tried to play around with some basic concepts. I have gotten a weird error in the following code.
I'm using Eclipse and get the following errors on the line where I try to add an ActionListener to the Button b:
"The method addActionListener(ActionListener) in the type Button is not applicable for the type new ActionAdapter(){}"
"ActionAdapter cannot be resolved to a type"
import java.awt.*;
import java.awt.event.*;
public class Test extends Frame{
private TextField text = new TextField(20);
Button b;
private int num_clicks = 0;
public static void main(String args[]){
Test appwind = new Test("title");
appwind.setSize(300,300);
appwind.setTitle("Irrelevant");
appwind.setVisible(true);
}
public Test(String title)
{
super(title);
setLayout(new FlowLayout());
addWindowListener(new WindowAdapter(){
public void WindowClosing(WindowEvent e) {
System.exit(0);}});
b = new Button("Click");
add(b);
add(text);
b.addActionListener(
new ActionAdapter()
{
public void actionPerformed(ActionEvent e)
{
num_clicks++;
text.setText("number of times clicked: " + num_clicks);}
});
}
}
Adapter classes are convenience classes provided when the underlying interface has 2 or more methods. ActionListener only has one method - Use ActionListener instead
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
...
}
});

Categories

Resources