I created this little test program. It has 2 buttons and 2 labels. I want to know how I can use 2 buttons. So when I press button-1 then I change the text for text-1 and when I press button-2 then I change text for text-2. I just wanna get an idea of how I can use multiple buttons.
My code:
JLabel text1, text2;
JButton button1, button2;
public Game(String title) {
super(title);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
getContentPane().setLayout(new FlowLayout());
addComponents();
setSize(250, 250);
setResizable(false);
}
public void addComponents() {
text1 = new JLabel();
getContentPane().add(text1, text2);
text2 = new JLabel();
getContentPane().add(text2);
button1 = new JButton("Button");
getContentPane().add(button1);
button1.addActionListener(this);
button2 = new JButton("Button 2");
getContentPane().add(button2);
button2.addActionListener(this);
}
#Override
public void actionPerformed(ActionEvent e) {
}
I'm new to programming, so I would also like if someone could write some comments for the code. Just so I get an idea on how the code for multiple buttons work.
In your actionPerformed method you can get the source of the action
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == button1){
//Do Something
}else if(e.getSource() == button2){
//Do Something Else
}
There are various approaches to add listeners to buttons, here just a couple:
Inner
If you don't have to do much actions in each button you can add inner listener in each button
button1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// DO STUFF
}
});
Common Listener
If you have more than 2 buttons (i guess your app will be bigger) you can use your actionPerformed(ActionEvent e) and get source of the action
#Override
public void actionPerformed(ActionEvent e) {
JButton source = (JButton) e.getSource();
if(source.equals(button1)){
// DO STUFF
}
}
Use actionCommand to clarify
To clarify this approach I would reccommend to use JButton.setActionCommand(stringCommand) so after you can use a switch:
Declaring buttons:
button1.setActionCommand("command1");
button2.setActionCommand("command2");
In ActionListener::actionPerformed()
public void actionPerformed(ActionEvent e) {
String command = ((JButton) e.getSource()).getActionCommand();
switch (command) {
case "command1":
// DO STUFF FOR BUTTON 1
break;
case "command2":
// DO STUFF FOR BUTTON 2
break;
}
}
Using Java 8, its it much more concise to add ActionListeners:
button.addActionListener(ae -> System.out.println("foo"));
Using multiple statements:
button.addActionListener(ae -> {
System.out.println("foo");
System.out.println("bar");
});
You should not use setVisible(true) before the components are added.
There are a few ways to deal with more elements in an ActionEvent:
e.getSource() returns the object on which the event occurred. So, if button1 was pressed, e.getSource() will be the same as button1 (and e.getSource()==button1 will thus be true)
You can use separate classes for each ActionEvent. If you would add the ActionListener "Button1ActionEvent" [button1.addActionListener(new Button1ActionEvent());] you have to create this class, let it implement ActionListener and add the method actionPerformed as you had in your main class. Also, you can create a listener inside of the addActionListener-method [button1.addActionListener(new ActionListener() { // actionPerformed-method here });]
Related
So for my program i have three buttons;
Button1: 8
Button2: 5
Button3: 3
public void actionPerformed(ActionEvent e) {
JButton b1= (JButton) e.getSource();
JButton b2= (JButton) e.getSource();
String button= b1.getText();
String button2 = b2.getText();
System.out.println("b1: " + button);
System.out.println("b2: " + button2);
I'm trying to check which buttons are pressed and storing them into the variable. So when the user presses 8, button should be 8, and once they press any second button, button2 should get that button
Do i make a new ActionEvent?
Currently both your buttons refer to the same source (I.e the same button)
If the actions to be triggered are similar in nature (for example, the buttons in MineSweeper, they are different buttons, but the actions to be triggered are the same), then you don't have to create multiple action listeners for multiple buttons. You can let your buttons add the same action listener:
//Example
class MyPanel extends JPanel{
private JButton btn1, btn2;
public MyPanel(){
btn1 = new JButton("Button 1");
btn2 = new JButton("Button 2");
ButtonHandler bn = new ButtonHandler();
btn1.addActionListener(bh);
btn2.addActionListener(bh);
}
}
Infact, what you wanted to do is just a one-liner:
private class ButtonHandler implements ActionListener{
#Override
public void actionPerformed(ActionEvent e){
System.out.println((JButton)e.getSource().getText());
}
}
However, if you have different actions for different buttons (for example, Start Game and Exit Game), then you can create separate action listeners for them.
So maybe you want to check the source of the event? Like:
public void actionPerformed(ActionEvent e) {
if (e.getSource() == b1) {
System.out.println("b1 pressed");
} else if (e.getSource() == b2) {
System.out.println("b2 pressed");
} else {
System.out.println("some other button pressed");
}
}
and you should really create different buttons outside of the scope of this actionPerformed method!
EDIT
The example solution by user3437460 is much better than this oneā¦
Every component can hold information on it, by putClientProperty();
This mechanism is kind of map, so can hold few named objects. We use only one.
This obcjet (pie of information) is not visible for user, it is not text written on button like getText() in few tries, is only for consuming by algorithm. There can live not only primitives or strings, but live objects too.
class MyPanel extends JPanel{
private JButton btn1, btn2;
public MyPanel(){
btn1 = new JButton("Button 1");
btn1.putClientProperty("myinternalsense", 8); // <-- here
btn2 = new JButton("Button 2");
btn1.putClientProperty("myinternalsense", 5); // <-- here
btn1.putClientProperty("myfunctor", new MyFunctor() ); // <-- here
ButtonHandler bn = new ButtonHandler();
btn1.addActionListener(bh);
btn2.addActionListener(bh);
}
}
This information is accessible in any context, for example common event handler to many buttons.
private class ButtonHandler implements ActionListener{
#Override
public void actionPerformed(ActionEvent e){
System.out.println((JButton)e.getSource().getClientPropertygetText("myinternasense")); // <-- here
}
}
Is there any way to get the source of an event? I know event.getSource() however, is there any way to convert it into a string?
For example, if the source is a button, button1, is there anyway to assign the value button1 to a string variable? (I'm dealing with a lot of buttons and so, I can't write if statements)
For the sake of clarity:
The getSource() method returns the object from which the Event initially occurred. You could use this to get some sort of property from the element, like the text inside a label or the name of a button.
These are Strings, but if you chose to go this route, I would make sure you pick something that is uniform across all components that will be calling that ActionListerner.
This is where getActionCommand() might come in handy. You can set unique 'identifiers' when components are created, and the access them later.
JButton button = new JButton("Button");
button.setActionCommand("1");
JButton button = new JButton("Button");
button.setActionCommand("2");
Then you can compare these later using any method you like, or you could do something fancy, like this (because you said you didn't want to use if-else statements):
String command = e.getActionCommand();
int i = Integer.parseInt(command);
switch (i) {
case 1: // do something
break;
}
According to the Java docs:
Returns the command string associated with this action. This string allows a "modal" component to specify one of several commands, depending on its state. For example, a single button might toggle between "show details" and "hide details". The source object and the event would be the same in each case, but the command string would identify the intended action.
Keep in mind that I think this is best approach only if you are using one ActionListerner for lots of components. As another answer pointed out, you could just make unique ActionListeners per each button.
Hope this helps you!
You can pass anything you want to an action listener through the constructor, as DaaaahWhoosh stated in his comment.
package com.ggl.fse;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ButtonActionListener implements ActionListener {
private String buttonText;
public ButtonActionListener(String buttonText) {
this.buttonText = buttonText;
}
#Override
public void actionPerformed(ActionEvent event) {
// TODO Auto-generated method stub
}
}
The buttonText String will be available in the actionPerformed method.
You can use a specific ActionListener for each JButton. Try this code:
private static String text;
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(200, 200, 200, 200);
frame.setLayout(new BorderLayout());
JButton button1 = new JButton("Button 1");
button1.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
text = button1.getText();
JOptionPane.showMessageDialog(null, "Text is: " + text);
}
});
JButton button2 = new JButton("Button 2");
button2.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
text = button2.getText();
JOptionPane.showMessageDialog(null, "Text is: " + text);
}
});
frame.add(button1, BorderLayout.NORTH);
frame.add(button2, BorderLayout.SOUTH);
frame.setVisible(true);
}
I want to remove JButton when user click JButton.
I know that I should use remove method, but it did not work.
How can I do this?
Here is my code:
class Game implements ActionListener {
JFrame gameFrame;
JButton tmpButton;
JLabel tmpLabel1, tmpLabel2, tmpLabel3, tmpLabel4;
public void actionPerformed(ActionEvent e) {
gameFrame.remove(tmpLabel1);
gameFrame.getContentPane().validate();
return;
}
Game(String title) {
gameFrame = new JFrame(title);
gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gameFrame.setBounds(100, 100, 300, 500);
gameFrame.setResizable(false);
gameFrame.getContentPane().setLayout(null);
tmpLabel4 = new JLabel(new ImageIcon("./images/bomber.jpg"));
tmpLabel4.setSize(200, 200);
tmpLabel4.setLocation(50, 100);
tmpButton = new JButton("Play");
tmpButton.setSize(100, 50);
tmpButton.setLocation(100, 350);
tmpButton.addActionListener(this);
gameFrame.getContentPane().add(tmpLabel4);
gameFrame.getContentPane().add(tmpButton);
gameFrame.setVisible(true);
}
}
If hiding the button instead of removing works for your code then you can use:
public void actionPerformed(ActionEvent event){
tmpButton.setVisible(false);
}
for the button.But the button is just hidden not removed.
The simplest solution might be to...
Attach an ActionListener to the button, see How to Use Buttons, Check Boxes, and Radio Buttons and How to Write an Action Listeners for more details
When the ActionListener is clicked, extract the source of the event, JButton buttonThatWasClicked = (JButton)actionEvent.getSource()
Remove it from it's parent...
For example...
Container parent = buttonThatWasClicked.getParent();
parent.remove(buttonThatWasClicked);
parent.revaidate();
parent.repaint();
As some ideas...
First of all in your actionPerformed method you need to check that the button is clicked or not. And if the button is clicked, remove it. Here's how :
if(e.getSource() == tmpButton){
gameFrame.getContentPane().remove(tmpButton);
}
add this to your actionPerformed Method
don't add your button to jframe but add each component you want!
public void actionPerformed(ActionEvent event)
{
//gameFrame.getContentPane().add(tmpButton); -=> "Commented Area"
gameFrame.getContentPane().validate();
}
or hide your button like this
public void actionPerformed(ActionEvent event)
{
tmpButton.setVisible(false);
}
I am making an applet and as part of my applet, I want this to happen: When the user presses "OK", the old components (some radio buttons) are removed, and a new JPanel is added, with a bunch of textfields.
However, I cannot figure out how to add a new component to the applet after it has started. I made the problem simpler by ignoring the removal part (Which I know how to do) and just adding a simple JLabel instead, but even that won't add!
Here is my code so far:
// imports omitted
public class Class extends Applet implements ActionListener
{
Button okButton;
CheckboxGroup radioGroup;
Checkbox radio1;
Checkbox radio2;
Checkbox radio3;
JLabel j;
public void init()
{
setLayout(new FlowLayout());
okButton = new Button("OK");
j = new JLabel("hello");
radioGroup = new CheckboxGroup();
radio1 = new Checkbox("Red", radioGroup,false);
radio2 = new Checkbox("Blue", radioGroup,true);
radio3 = new Checkbox("Green", radioGroup,false);
add(okButton);
add(radio1);
add(radio2);
add(radio3);
okButton.addActionListener(this);
}
public void repaint(Graphics g)
{
if (radio1.getState()) add(j);
}
public void actionPerformed(ActionEvent evt)
{
if (evt.getSource() == okButton) repaint();
}
}
What am I doing wrong?
You shouldn't override the repaint method, and certainly not add a component in this method. Just remove the radio buttons from the applet (using its remove method) and add the label in the applet in your actionPerformed method, the same way you add them in the init method.
You might have to call validate after.
Add components and then call validate() of your container. In this case yourApplet.validate(). This will trigger repainting and rearranging of all elements.
you could do something like
JFrame fr= new JFrame(); // global variables
JPanel panelToBeAdded = new JPanel();
JPanel initialPanel = new JPanel();
JTextField fieldToBeAdded = new JTextField();
panelToBeAdded.setPreferredSize( new Dimension(400,400));
initialPanel.setPreferredSize( new Dimension(400,400));
initialPanel.setVisible(true);
fr.add(initialPanel);
fr.setVisible(true);
fr.pack();
public void actionPerformed(ActionEvent ae) {
initialPanel.setVisible(false);
//radiobuttons.setVisible(false);---> hide the radio buttons
panelToBeAddedd.add(fieldToBeAddedd);
panelToBeAddedd.setVisible(true);
fr.add(panelToBeAddedd);
}
public void repaint( Graphics g ) {
// do something
}
What am I doing wrong?
Your repaint(Graphics) method is not the same method you are calling in your actionPerformed method.
Also, repaint is a pretty bad name for a method which is adding a new component.
public void swapComponents()
{
if (radio1.getState()) {
remove(radio1);
remove(radio2);
remove(radio3);
add(j);
validate();
}
}
public void actionPerformed(ActionEvent evt)
{
if (evt.getSource() == okButton) {
swapComponents();
}
}
When the user presses "OK", the old components (some radio buttons) are removed, and a new JPanel is added, with a bunch of textfields.
Use a CardLayout, as shown here. It is perfect for situations like this.
How can I make it so that when I press enter in a JTextField it activates a specific JButton? What I mean is something along the lines of a web page form where you can press enter to activate the button in the form.
You should use an Action for the JButton:
Action sendAction = new AbstractAction("Send") {
public void actionPerformed(ActionEvent e) {
// do something
}
};
JButton button = new JButton(sendAction);
Then you can set the same action for a JTextField or even on a MenuItem if you want the same action to be available in the Menu:
JTextField textField = new JTextField();
textField.setAction(sendAction);
Something like this should work:
textField.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
button.requestFocusInWindow();
}
});
You can achieve this by adding the default behavior to the button, like this
cmdLogin.setDefaultCapable(true); // by default, this is true
this.getRootPane().setDefaultButton(cmdLogin); // here `this` is your parent container
I'd do something like the following:
textField.addKeyListener(
new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
button.doClick();
}
}
});
}