Add actionperformed to a button through another class - java

I'm trying to learn methods and classes
I created a small tool where class Main is to run it, class SWing to create the frame, class Verb to create a button to add to Swing and as well to do the action performed, my question here is that, how can I make the action performed really works via verb Class.
let's say I want to get text from textfield and to concatenate it with textfiled1 and to show the answer on textfield2.
here is my code
1- my main class
package Abo;
public class Main {
public static void main (String[]args){
Swing runFrame = new Swing(); // creating a variable for class Swing
runFrame.Run(); // to run the Swing
}
}
2- my Swing
package Abo;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JTextField;
public class Swing extends JFrame {
public JTextField textField;
public JTextField textField_1;
public JTextField textField_2;
public Swing() {
// creating the frame
getContentPane().setLayout(new GridLayout(2,2,5,5));
textField = new JTextField();
getContentPane().add(textField);
textField.setColumns(10);
textField_1 = new JTextField();
getContentPane().add(textField_1);
textField_1.setColumns(10);
textField_2 = new JTextField();
getContentPane().add(textField_2);
textField_2.setColumns(10);
textField_2.setEditable(false);
// adding the btn from another class
Verb addBTN = new Verb();
getContentPane().add(addBTN.BTN());
}
public void Run(){
// setting the frame
Swing frame = new Swing();
frame.setVisible(true);
frame.setSize(300,400);
frame.setLocationRelativeTo(null);
frame.setResizable(false);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
}
3- verb class
package Abo;
import javax.swing.JButton;
public class Verb extends JButton {
// creating the btn constructor
public JButton BTN(){
JButton btn1 = new JButton("First Button");
return btn1;
}
}
thank you in advance

Well in your verb class just add this to btn1
btn1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
//Execute when button is pressed
}
});

I noticed that Verb is extending JButton, but you are opting to write a method that returns a JButton inside of it.
If you want Verb to be a JButton that is always called "First Button", then I would instead modify Verb's constructor.
One way to do that would be like this:
package Abo;
import javax.swing.JButton;
public class Verb extends JButton {
public Verb() {
super("First Button"); //super calls the constructor of the parent of this class, in this case that is JButton
}
}
Now since you are extending JButton, whenever you make a Verb, it will also be a JButton with the text "First Button"
Now you can add your ActionListener to Verb directly.
By doing:
Verb addBTN = new Verb();
addBTN.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
textField_2.setText(textField.getText() + textField_1.getText());
}
});
However, in order to access your text fields inside of the actionlistener, you will need to make them final.
final textField = new JTextField(); // do this for all text fields
Also, just as good practice, unless you are planning to add more functionality than the default constructor to Verb, I would just use a JButton instead of making your own class.

Related

Why can´t I click on the JButtons?

Hey I am a beginner and I have wrote the following code in java, but I can´t click on the JButtons. The program includes three clases - Main, Frame and Actionhandler. My goal was to create a Frame with two buttons: Singleplayer and Mulitplayer. I wanted to test if they work, but I can´t click them. Can anyone help me please?
This is the Main class:
public class Main {
public static void main (String [] args) {
new Frame ();
}
}
This is the Frame class:
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Frame extends JFrame {
public static Object multi;
public static Object single;
Frame() {
// Frame
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setExtendedState(JFrame.MAXIMIZED_BOTH);
this.setLocationRelativeTo(null);
//Layout in Frame
this.setLayout(new GridLayout(2,1));
this.setVisible(true);
// Buttons in Main Menu
JButton single = new JButton("Singleplayer");
JButton multi = new JButton("Multiplayer");
// specify single button
single.setBounds(200,100,250,80);
single.setForeground(Color.GREEN);
single.setBackground(Color.LIGHT_GRAY);
single.setOpaque(true);
single.setBorder(BorderFactory.createLineBorder(Color.BLACK));
single.setFont(new Font("Comic Sans",Font.BOLD,25));
single.addActionListener(new ActionHandler());
//specify multi button
multi.setBounds(800,100,250,80);
multi.setForeground(Color.GREEN);
multi.setBackground(Color.GRAY);
multi.setOpaque(true);
multi.setFont(new Font("Comic Sans",Font.BOLD,25));
multi.setBorder(BorderFactory.createLineBorder(Color.BLACK));
multi.addActionListener(new ActionHandler());
// add Buttons to Frame
this.add(single);
this.add(multi);
}
}
This is the ActionHandler class:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ActionHandler implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == Frame.multi) {
System.out.println("You have clicked on Singleplayer");
if(e.getSource() == Frame.single) {
System.out.println("You have clicked on Multiplayer");
}
}};
}
You can click on the buttons fine. They just won't do anything because of how you've wired the program:
public class Frame extends JFrame {
public static Object multi; // this is null
public static Object single; // and so is this
Frame() {
// Frame
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setExtendedState(JFrame.MAXIMIZED_BOTH);
this.setLocationRelativeTo(null);
//Layout in Frame
this.setLayout(new GridLayout(2,1));
this.setVisible(true);
// Buttons in Main Menu
JButton single = new JButton("Singleplayer"); // this is a new *local* variable
JButton multi = new JButton("Multiplayer"); // and so is this:
You are initializing local variables that have the same name as your static class fields, and you're leaving the same static class fields null, a situation known as "variable shadowing", and so in your listeners, you check if the source is the null static field. Which won't work.
So in your listener:
public void actionPerformed(ActionEvent e) {
if(e.getSource() == Frame.multi) {
You're testing if a null variable is the button that was pressed, and this will not work.
One simple solution is to not re-declare the multi and single variables, to assign your JButtons to these public static fields by changing this:
JButton single = new JButton("Singleplayer");
JButton multi = new JButton("Multiplayer");
to this:
single = new JButton("Singleplayer");
multi = new JButton("Multiplayer");
This would sort-of work. You'd have do do some casting to add these JButton objects to the container since the variables are Object, not JButton. But this would be a bad idea because you'd be throwing out the OOPs baby with the bathwater, discarding encapsulation completely.
Best not to throw out OOPs rules with public static (non-constant) fields and instead work with them. Better to use constant Strings to be passed into your JButtons and then test for them using the ActionEvent's actionCommand property:
public class Frame extends JFrame {
public static String SINGLE_PLAYER = "Single Player";
public static String MULTI_PLAYER = "Multi Player";
Frame() {
// Frame
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setExtendedState(JFrame.MAXIMIZED_BOTH);
this.setLocationRelativeTo(null);
//Layout in Frame
this.setLayout(new GridLayout(2,1));
this.setVisible(true);
// Buttons in Main Menu
JButton single = new JButton(SINGLE_PLAYER); // this is a new *local* variable
JButton multi = new JButton(MULTI_PLAYER); // and so is this:
in the listener:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ActionHandler implements ActionListener{
#Override
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals(Frame.MULTI_PLAYER)) {
System.out.println("You have clicked on Multi Player");
} else {
// ...
}
}};
}
Other problems with your code include:
Don't name your class Frame since this clashes with the name of class in the core Java library, java.awt.Frame. Name it something unique to avoid confusion
Avoid setting bounds, sizes and such. Let the GUI, its layout managers and component preferred sizes do the sizing by calling pack() on the top-level window (JFrame, JDialog,...) after adding components
Call .setVisible(true) on the top-level window after adding all components.
This looks like it will display as a sub-window or dialog window, and you might want to show this portion of the GUI in a modal JDialog, not in a JFrame.

Java/Swing JButton does not display its text and does not perform its action

I want to write a simple street crossing traffic light system. I want to make a button which will start the whole program (open up the GUI of the traffic light system). But already my first button starts to make problems. It doesnt display its text and the action it should perform won't happen. I am really a beginner so its probably some dumb and obvious fault but please have a look I would be really happy ^^
package kreuzung;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.FlowLayout;
import javax.swing.JFrame;
public class HomeFrame extends JFrame{
public HomeFrame(String title) {
super(title);
this.setLayout(new FlowLayout(FlowLayout.CENTER));
Button test = new Button("noAction");
Container cont = getContentPane();
cont.add(test, BorderLayout.CENTER);
}
}
And this would be the generated button which doesn't do the things its supposed to do
package kreuzung;
import javax.swing.Action;
import javax.swing.JButton;
public class Button extends JButton{
private String actionName;
public Button(String actionName) {
this.actionName = actionName; //set the Action name of this button
JButton button = new JButton(); //instantiate this Button
button.setText(actionName); //set the Action Name as Button Text
button.setSize(30, 30);
button.setBounds(5, 5, 25, 25);
button.addActionListener(new Evt(this.actionName)); //add an Action Listener to the button
//and gets the Action from the Evt Class
}
}
And last but not least here's the Evt class which should take care of the action performing
package kreuzung;
import java.awt.event.*;
import javax.swing.JFrame;
public class Evt implements ActionListener {
private String actionName;
public Evt(String actName) {
this.actionName = actName;
}
#Override
public void actionPerformed(ActionEvent e) {
switch(actionName) {
case "noAction":
JFrame frame = new HomeFrame("Home");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 400);
frame.setVisible(true);
break;
}
}
}
There are several errors in your code:
You shouldn't extend JFrame, see Extends JFrame vs. creating it inside the program
Don't call setBounds(...) the Layout Managers will take care of positioning your components
Don't leave too much extra space between lines or after / before opening / closing braces {} it becomes hard to read
Don' call Button as a class name, it could be confused with java.awt.Button class.
It doesnt display its text and the action it should perform won't happen
In this class:
public class Button extends JButton {
private String actionName;
public Button(String actionName) {
this.actionName = actionName;
JButton button = new JButton();
button.setText(actionName);
button.setSize(30, 30);
button.setBounds(5, 5, 25, 25);
button.addActionListener(new Evt(this.actionName));
}
}
You extend from JButton and then you create a JButton inside of it! so, you have 2 JButtons, the one from the class (inherited) and the one you create inside it. But you're setting the text to the one created inside but you're adding the other one (without text) to your JFrame.
In a metaphor, it's like:
You write in a page something
You get a new white page and add it to your book, instead of adding the one you wrote in to your book.
There's no need to extend JButton in your current program, so just create a new JButton instance and that's it.
Otherwise if you really want to use a custom JButton class do this:
public class MyCustomButton extends JButton { // Change class name
private String actionName;
public MyCustomButton(String actionName) {
super(actionName); //Sets the text
this.actionName = actionName;
button.addActionListener(new Evt(this.actionName));
}
}
You do not really need to create a JButton's children class since you do not add any particular attribute to it.
Instead you should be able to make it works this way:
public class HomeFrame extends JFrame{
private static final String BUTTON_ACTION_NAME = "myActionName";
public HomeFrame(String title) {
super(title);
this.setLayout(new FlowLayout(FlowLayout.CENTER));
JButton test = new JButton();
test.setText(BUTTON_ACTION_NAME);
test.setSize(30, 30);
test.setBounds(5, 5, 25, 25);
test.addActionListener(new Evt(BUTTON_ACTION_NAME));
Container cont = getContentPane();
cont.add(test, BorderLayout.CENTER);
}
}

How to call a panel from a button with ActionListener

So I'm making a simple program that jumps from panel to panel and am using an actionlistener Button to make the jump. What kind of method or operation do I use to jump from panel to panel?
I tried to use setVisible(true); under the action listener, but I get just a blanks screen. Tried using setContentPane(differentPanel); but that doesn't work.
ackage Com.conebind.Characters;
import Com.conebind.Tech.TechA16;
import Com.conebind.Overviews.OverviewA16;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Char_A16 extends JFrame {
private JButton combosButton16;
private JButton techButton16;
private JButton overviewButton16;
private JLabel Image16;
private JPanel panel16;
private JPanel panelOverviewA16;
public Char_A16() {
overviewButton16.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
OverviewA16 overview16 = new OverviewA16();
overview16.setVisible(true);
overview16.pack();
overview16.setContentPane(new Char_A16().panelOverviewA16);
}
});
techButton16.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
//Todo
}
});
}
private void createUIComponents(){
Image16 = new JLabel(new ImageIcon("Android 16.png"));
}
public static void main (String[] args){
JFrame frame = new JFrame("Android 16");
frame.setContentPane(new Char_A16().panel16);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);}
}
The setContentPane(OverviewA16) doesn't work because there's not an object that defines the panel.
Please check this demo project showing how to use CardLayout with IntelliJ IDEA GUI Designer.
The main form has a method that switches between 2 forms displayed inside it:
public void showPanel(String id) {
final CardLayout cl = (CardLayout) cardPanel.getLayout();
cl.show(cardPanel, id);
}
Both forms are added to the card layout during the main form initialization:
FormOne one = new FormOne();
one.setParentForm(this);
cardPanel.add(one.getPanel(), FORM_ONE);
FormTwo two = new FormTwo();
two.setParentForm(this);
cardPanel.add(two.getPanel(), FORM_TWO);
final CardLayout cl = (CardLayout) cardPanel.getLayout();
cl.show(cardPanel, FORM_ONE);
A reference to the main parent form is passed to these 2 forms using setParentForm() method so that FormOne and FormTwo classes can access the showPanel() method of the MainForm.
In a more basic case you may have a button or some other control that switches the forms
located directly on the MainForm, then you may not need passing the main form reference to the subforms, but it can be still useful depending on your app logic.

Extending a java class whilst also altering it

I've been a lurker on stackoverflow for some time. I'm teaching myself Java, so bear with me if this is a rather elementary question (I couldn't find the answer on here though).
If I have a java class (like the one below), which I wish to use in future classes in a slightly different way (e.g. changing the button text/or output), is there a way to do this by extending the original class?
In the case below I have a JFrame with two buttons which print different text to the console. I simply want to extend this class whilst changing one of the button names.
ORIGINAL CLASS:
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class FrameIt extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
new FrameIt().setVisible(true);
}
public FrameIt() {
super("Make a choice");
setSize(600, 600);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new GridLayout());
JButton button = new JButton("Click Me.");
JButton button2 = new JButton("No, you should Click Me!");
button.addActionListener(this);
button2.addActionListener(this);
add(button);
add(button2);
}
#Override
public void actionPerformed(ActionEvent e) {
String name = e.getActionCommand();
if(name.equals("Click Me")){
System.out.println("That was actually the right choice.");
}else{
System.out.println("Poor choice.");
}
}
}
CLASS THAT EXTENDS:
import javax.swing.JButton;
public class Alterations extends FrameIt{
private static final long serialVersionUID = 1L;
public static void main(String args[]){
new Alterations().setVisible(true);
System.out.println("Doing it");
}
public Alterations(){
JButton button2 = new JButton("Slightly different button");
}
}
Thanks.
Creating the JButton instance in the sub-class Alterations will make no difference, since you don't connect it to anything.
One way to handle it is to change the constructor of the original class. You can make the name of the button originate from a method call :
Change :
JButton button2 = new JButton("No, you should Click Me!");
To :
JButton button2 = new JButton(getSecondButtonName ());
Then getSecondButtonName() can return "No, you should Click Me!" in the original class and you can override it in the sub-class to return "Slightly different button".
An alternative would be to remove the original button in the constructor of the sub-class and add the new button.
These solutions make sense only if there's a real reason to create a sub-class in the first place. If the only difference between the base class and the sub-class is the name of one button, there's no reason to create a sub-class.

Display text on Jlabel with if statements and radio buttons

I followed a few different tutorials on how to get this working and I just can't seem to get my buttons to update the JLabel. Can you tell me which part is incorrect and lead me in the right path of what to fix. This has been plaguing me for hours.
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.SwingConstants;
public class CoinApp extends JFrame {
private JLabel label;
private JRadioButton rdbtnNewRadioButton_3, rdbtnNewRadioButton, rdbtnNewRadioButton_1, rdbtnNewRadioButton_2;
public CoinApp() {
setBounds(50, 50, 500, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
ButtonGroup buttonGroup = new ButtonGroup();
JPanel panel = new JPanel();
getContentPane().add(panel);
JRadioButton rdbtnNewRadioButton_3 = new JRadioButton("");
buttonGroup.add(rdbtnNewRadioButton_3);
rdbtnNewRadioButton_3.setIcon(new ImageIcon(getClass().getResource("UsCent.png")));
panel.add(rdbtnNewRadioButton_3);
JRadioButton rdbtnNewRadioButton = new JRadioButton("");
buttonGroup.add(rdbtnNewRadioButton);
rdbtnNewRadioButton.setIcon(new ImageIcon(getClass().getResource("UsNickel.png")));
panel.add(rdbtnNewRadioButton);
JRadioButton rdbtnNewRadioButton_1 = new JRadioButton("");
buttonGroup.add(rdbtnNewRadioButton_1);
rdbtnNewRadioButton_1.setIcon(new ImageIcon(getClass().getResource("UsDime.png")));
panel.add(rdbtnNewRadioButton_1);
JRadioButton rdbtnNewRadioButton_2 = new JRadioButton("");
buttonGroup.add(rdbtnNewRadioButton_2);
rdbtnNewRadioButton_2.setVerticalAlignment(SwingConstants.TOP);
rdbtnNewRadioButton_2.setIcon(new ImageIcon(getClass().getResource("UsQuarter.png")));
panel.add(rdbtnNewRadioButton_2);
rdbtnNewRadioButton_3.setSelected(true);
label = new JLabel("CENT w:2.5 d:19.1", JLabel.CENTER);
add(label);
}
**
public void actionPerformed(ActionEvent evt) {
if ( rdbtnNewRadioButton_3.isSelected() ) {
label.setText("CENT w:2.5 d:19.1");
}
else if ( rdbtnNewRadioButton.isSelected() ) {
label.setText("NICKEL w:5.0 d:21.2");
}
else if ( rdbtnNewRadioButton_1.isSelected() ) {
label.setText("DIME w:2.3 d:17.9");
}
else if ( rdbtnNewRadioButton_2.isSelected() ) {
label.setText("QUARTER w:5.7 d:24.3");
}
} // end actionPerformed()
**
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
CoinApp frame = new CoinApp();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
for( Coin el : Coin.values())
{
System.out.println(el);
}
}
}
Start by taking a look at How to Write an Action Listeners
In order for your buttons to provide notification, you must register an ActionListener within them.
In order for your buttons to call your actionPerformed method however, you need to implement the ActionListener interface...
public class CoinApp extends JFrame implements ActionListener {
//...
#Override
public void actionPerformed(ActionEvent evt) {
You should add the #Override annotation to methods you believe you are overriding from parent classes or interfaces, it will give you a compiler warning if you've done something wrong, like misspelt it for example.
Now you can register the ActionListener with your buttons...
rdbtnNewRadioButton_3.addActioinListener(this);
Updated...
Also, beware, you are shadowing your variables...
What I mean by this is, you are declaring your variables as instance/class variables...
private JRadioButton rdbtnNewRadioButton_3, rdbtnNewRadioButton, rdbtnNewRadioButton_1, rdbtnNewRadioButton_2;
Which is good, but in your constructor, you are re-declaring them...
public CoinApp() {
//...
JRadioButton rdbtnNewRadioButton_3 = new JRadioButton("");
This means when you go to reference rdbtnNewRadioButton_3 somewhere else in your program, it will be null.
You should be using something like...
public CoinApp() {
//...
rdbtnNewRadioButton_3 = new JRadioButton("");
You need to hook up your event handler method (actionPerformed) to each of the radio buttons. To do this you need to register an ActionListener to each radio button. The most convenient way for you to do this is to have your main class implement the ActionListener interface, and then call addActionListener on each radio button a reference to this
Also note that your event handler method will currently cause you problems because you are never actually setting the class level members (fields) (rdbtnNewRadioButton_3 etc). You are actually creating new local variables in your constructor with the same name that 'hide' the class level fields, which then become inaccessible when they fall out of scope, leaving the class level variables null.
Your constructor code should look like this:
rdbtnNewRadioButton_3 = new JRadioButton("");
Instead of
JRadioButton rdbtnNewRadioButton_3 = new JRadioButton("");
Good luck!

Categories

Resources