Actionlisteners in constructor - java

I am trying to create NewCard class, with implements a frame. How can I add Actionlisteners to elements in constructor of NewCard class? I can't put Actionlistener into constructor, and when I put it outside, element "field" is invisible for saveButtonListener block..
Second question: class Record in try block throws two exceptions, why try block generate error?
package Interface;
import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.awt.event.*;
import Engine.*;
class NewCard extends JFrame
{
NewCard()
{
JFrame Card = new JFrame();
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setTitle("New Card");
setSize(340, 580);
setVisible(true);
Container contentPane = getContentPane();
contentPane.setLayout(null);
// Field
JTextField field = new JTextField();
contentPane.add(field);
field.setBounds(110,15,200,25);
// Button:
JButton saveButton = new JButton("Save");
powZawartosci.add(saveButton);
saveButton.setBounds(95,495,150,25);
saveButtonListener listener1 = new saveButtonListener();
saveButton.addActionListener(listener1);
}
private class saveButtonListener implements ActionListener
{
try
{
#Override
public void actionPerformed(ActionEvent event)
{
new Record(field.getText());
}
}
catch(IOException e)
{
System.out.println("IOException");
}
catch(SQLException e)
{
System.out.println("SQLException");
}
finally
{
}
}
}

You could put your action listener inside constructor like this:
final JTextField field = new JTextField();
...
saveButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
new Record(field.getText());
}
});

Pass field to the saveButtonListener by creating an appropriate constructor for the listener.
Or use an anonymous listener, as shown in Mersenne's answer.

regarding:
I can't put Actionlistener into constructor, ...
Who says you can't? Simply add the ActionListener...
JButton saveButton = new JButton("Save");
saveButton.addActionListener(new SaveButtonListener()); // capitalize class names
Or you can use anonymous inner classes, or even better, use AbstractActions.
Edit 1:
Regarding:
Second question: class Record in try block throws two exceptions, why try block generate error?
If you have a question about an exception, it makes lots of sense to show the exception.
Edit 2
Regarding:
class NewCard extends JFrame
{
NewCard()
{
JFrame Card = new JFrame();
Why have the class extend JFrame and create a JFrame inside the class that is never used?Best to not have the class extend JFrame but rather to create the JFrame when needed.

Related

JButton's actionPerformed doesn't change JTextField's text by using .setText() method

I have this code... in it it has a problem as in title: JTextField's text doesn't change when clicking the button. I don't know what the problem is, but I think actionPerformed is executed as the message dialog appears. I tried to use a constructor (of class Start) (instead of function "doIt") but it doesn't work either.
import javax.swing.*;
import java.awt.FlowLayout;
import java.awt.*;
import java.awt.event.*;
public class PalTransfer
{
public static void main(String[] args)
{
Starter starter = new Starter();
starter.doIt();
}
}
class Starter
{
JFrame PTMainFrame = new JFrame("In/Out - arch - access, ...");
JTextField TextFieldOfIP = new JTextField(20);
//String string = "I AM START OF STARTER";
void doIt()
{
PTMainFrame.setSize(900, 400); // Set the frame size
PTMainFrame.setLocationRelativeTo(null);
PTMainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JTextField TextFieldOfIP = new JTextField(20);
JButton jBtn = new JButton("I AM A BUTTON!");
PTMainFrame.add(jBtn);
PTMainFrame.add(TextFieldOfIP);
FlowLayout layoutManager = new FlowLayout(0,10,5);
PTMainFrame.setLayout(layoutManager);
TextFieldOfIP.setText("I am doIt() method!"); //+++++++++++++++++++++++++++
jBtn.addActionListener(new ButtonListener());
PTMainFrame.setVisible(true); // to do // put later
}
class ButtonListener implements ActionListener
{
#Override
public void actionPerformed(ActionEvent e)
{
JOptionPane.showMessageDialog(null, "hello?");
TextFieldOfIP.setText("I am actionPerformed of JButton!");
}
}
}
Why have you defined this twice.
JTextField TextFieldOfIP = new JTextField(20);
Remove it from the DoIt() method it will work.
You have your class attribute TextFieldOfIP that your ButtonListeners is doing the setText on. But additional you have a local variable called TextFieldOfIP in your doIt() method. And thats the object you are placing on your JFrame.
Remove this redefinition line: JTextField TextFieldOfIP = new JTextField(20); of your doIt() method. Then you are placing the same object on your JFrame that your ButtonListener is doing the setText on and everything will work as expected.

.getText(); not working for textField variable that is declared in another class

In trying to read the text that is entered into a textField, I used the actionlistener for a button right next to it. In this actionlistener class, I had an action performed method in which I created a string that was set equal to the textField.getText();. This class however has a problem recognizing textField variable from the previous class.
It is necessary for the .getText() or reading of the textField entry to be in the actionlistener class. I do not know what to try besides the code that I have listed down below.
public class MainClass {
public static void main(String args[]) {
JFrame frame = new JFrame ("Welcome");
frame.setVisible(true);
frame.setSize(500, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
frame.add(panel);
JLabel label = new JLabel("...");
panel.add(label);
JTextField text = new JTextField(20);
panel.add(text);
JButton SubmitButton = new JButton("Analyze");
panel.add(SubmitButton);
SubmitButton.addActionListener(new Action1());
}
static class Action1 implements ActionListener {
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
JFrame frame1 = new JFrame("Word Commonality");
frame1.setVisible(true);
frame1.setSize(500,200);
String ReceivedPath = text.getText();
System.out.println(ReceivedPath);
Error is present at second to bottom line of code. The error is "text cannot be resolved"
I expect that the text can be read and printed out in the console.
Your problem is revolved around function scoping to fix it you need a direct access to the JTextField object you can do so by instantiating a new action performed straight in the MainClass like this:
public class Main {
public static void main(String args[]) {
new MainClass();
}
}
Here I created a class only used to instantiate the window class
For the main class I suggest extending JFrame so you can inherit all of it methods.
//Imports
public class MainClass extends JFrame {
private JPanel panel;
private JLabel label;
private JTextField text;
private JButton SubmitButton;
public MainClass(){
super("Welcome");
setSize(500, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
panel = new JPanel();
add(panel);
label = new JLabel("...");
panel.add(label);
text = new JTextField(20);
panel.add(text);
SubmitButton = new JButton("Analyze");
panel.add(SubmitButton);
SubmitButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String ReceivedPath = text.getText();
System.out.println(ReceivedPath);
}
});
setVisible(true);
}
}
This is how your class should look like.
Side notes:
Set visible is at the end otherwise the items will not be see able.
The MainClass is inheriting from JFrame so it can use all its methods without instatiating it look at inheritance(https://www.w3schools.com/java/java_inheritance.asp)
The action performed now can acces the text JTextField because it is a class attribute.
If the solution is correct please think of marking this answer as final. Thank you
If you place the getText() outside the ActionListener, it will be read immediately after creating the panel. That is why it is empty. You can make the ActionListener assign a value to a variable, but it will be empty until the action is performed.
Also see here: Swing GUI doesn't wait for user input

JButton in separate class won't change JTextField(Area) text in different class

I have a JFrame which contains 3 JPanels (each in a separate class). The first JPanel contains two JTextFields in which I write the name of the file to be read from and the condition to be fulfilled respectively. This doesn't really affect my question, so let's move on.
The second JPanel has a JTextArea.
The third JPanel has two JButtons (Load, Sort) which are supposed to load a list of entries that suffice the condition from the first JPanel and then reorganize them according to some rules (respectively).
THE PROBLEM:
Ok so, the first class is the JFrame class in which i just do the standard look and feel of the window.
The second class is the first JPanel with two JTextFields.
I won't give code for this one because the second JPanel code is shorter and has the same problem so I imagine that the same solution would apply.
Third class contains the JTextArea in which I should display certain entries from the text-file.
Code:
public class SecondPanel extends JPanel {
JPanel panel;
JTextArea lista;
public SecondPanel() {
panel = new JPanel();
list = new JTextArea("List");
list.setPreferredSize(new Dimension(200, 150));
this.add(list);
}
}
Moving on, the fourth class contains the Jbuttons and the ActionListener(Button listener). Ok so here is the part of the code from the button listener class
CODE:
private class ButtonListener implements ActionListener {
SecondPanel secondPanel = new SecondPanel();
FirstPanel firstPanel = new FirstPanel();
#Override
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals("Load")) {
//calls method that loads data from the text in a firstPanel field
loadData(firstPanel.theFile.getText());
for(int i = 0; i< students.length; i++) {
if(students[i]!=null) {
// doesn't write anything tried with .setText etc.
secondPanel.list.append(students[i]+"\n");
}
}
}
}
}
So the program won't get text when i type in the JTextField designated for the file path. And when i do it manually in the code, It won't write the changes to the list on the Window (JTextArea). But when i System.out.print to the console it prints the changes and lists entries correctly as well as any setText changes I make. It just won't write or read to and from the Window..
What should I do?
The problem is that you are calling your setText methods on the wrong objects.
In your listener class, you declared two new panels as class variables, and then you call your methods on them, but i think those panels are not the ones you really want to change.
You should first add your panels to your Jframe object, and refer to them on your ActionListener.
Here i provide you a minimal code which modifies a JTextArea when a JButton is pressed. (same for a JTextField)
import java.awt.*;
import javax.swing.*;
public class MyJFrame extends JFrame {
SecondPanel sPanel;
public MyJFrame() {
super("main");
Container c = getContentPane();
c.setLayout(new BorderLayout());
JButton button = new JButton("load");
button.addActionListener(new LoadListener());
c.add(sPanel = new SecondPanel(), BorderLayout.NORTH);
c.add(button, BorderLayout.SOUTH);
pack();
setVisible(true);
}
class SecondPanel extends JPanel {
public JTextArea list;
public SecondPanel() {
super();
list = new JTextArea("List");
list.setPreferredSize(new Dimension(200, 150));
add(list);
}
}
class LoadListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
sPanel.list.setText("new text for the jtext area");
}
}
public static void main(String[] args) {
new MyJFrame();
}
}

Inheriting classes in JButton

Hi guyz i have a prob in writing java code for my project as am unable to tackle that, i want my "Categories" button to perform action like it should show bread class in it but am unable to inherit it and put a pic on it so can anyone here just tell me whats the problem in it..
here is the code:
JButton b1 = new JButton("Categories");
b1.setSize(120,25);
b1.setLocation(130,650);
b1.setBackground(Color.LIGHT_GRAY) ;
b1.addActionListener(new AL());
f.add(b1);
public class AL implements ActionListener{
public void actionPerformed(ActionEvent ae){
JFrame f3 = new JFrame("Delicious Bakery");
f3.setVisible(true);
f3.setSize(400,200);
f3.add(Bread);
Now here is the Bread class:
public class Bread extends AL implements ActionListener
{
Bread()
{
ImageIcon BreadImage = new ImageIcon("C:\\Users\\Baba\\Downloads\\Documents\\Bread1.jpg");
JButton Bread = new JButton("Bread",BreadImage);
Bread.setSize(128,96);
}}
You appear to be making several basic mistakes including what looks to be trying to add a class that implements ActionListener to your GUI as if it were a button, but it's not. This suggests that you'd greatly benefit from first reading through the JButton Tutorial and the ActionListener Tutorial.
Note that if this were my project, I'd use AbstractActions a concept that is sort of like an "ActionListener on steroids". You would set your JButton with this Action and in doing so, gain the button its name text, its icon and its ActionListener behavior.
Some notes on your code:
JButton b1 = new JButton("Categories"); // (1)
b1.setSize(120,25); // (2)
b1.setLocation(130,650); // (3)
b1.setBackground(Color.LIGHT_GRAY) ;
b1.addActionListener(new AL()); // (4)
f.add(b1); // (5)
You here create a JButton with a String name text
Here you try to set absolute size, something that we don't recommend as doing this, and using null layouts leads to rigid hard to improve and debug programs
Same for setting locations
You appear to be adding an ActionListener OK
And then add your button to a container (the JFrame perhaps)?
public class AL implements ActionListener{ // (6)
public void actionPerformed(ActionEvent ae){
JFrame f3 = new JFrame("Delicious Bakery"); // (7)
f3.setVisible(true); // (8)
f3.setSize(400,200); // (9)
f3.add(Bread); // (10)
OK, so the AL class implements ActionListener and has an actionPerformed method, so far so good
OK, so inside it you create a new JFrame, a bit unusual since most GUI's have only one JFrame
You're calling setVisible(true) on the JFrame before adding components -- not code, since this may sometimes not allow the JFrame to fully render components added after this setVisible was called
Same notes as previous about setting sizes
Now you add Bread to the JFrame. But Bread looks to not be a component but rather only an ActionListener. This line should not compile.
public class Bread extends AL implements ActionListener { // (11)
Bread() {
// (12)
ImageIcon BreadImage = new ImageIcon("C:\\Users\\Baba\\Downloads\\Documents\\Bread1.jpg");
JButton Bread = new JButton("Bread",BreadImage); // (13)
Bread.setSize(128,96); // (14)
}
}
Your Bread class extends AL but also implements ActionListener which is redundant since AL already implements ActionListener.
You are creating an image icon using a file and an absolute path, a slight no-no. Better to use resources and absolute paths
OK you create a new JButton, but you give it the same name as the non-JButton class -- very confusing. Simply don't do this. Ever. Name your fields with unique names, and obey Java naming issues.
Same issue regarding setting sizes.
For example:
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;
public class TestBread extends JPanel {
// String to url for bread image
private static final String BREAD_IMG_PATH = "http://findicons.com/files/icons/339/"
+ "coffee_break/128/sliced_bread.png";
// preferred size of jpanel
private static final int PREF_W = 400;
private static final int PREF_H = 300;
private BreadAction breadAction; // our abstract action
private JButton breadButton; // our jbutton
public TestBread() {
Icon breadIcon = null;
try {
// get image and put into Icon
URL breadUrl = new URL(BREAD_IMG_PATH);
BufferedImage breadImg = ImageIO.read(breadUrl);
breadIcon = new ImageIcon(breadImg);
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
breadAction = new BreadAction("Bread", KeyEvent.VK_B, breadIcon); // create Action
breadButton = new JButton(breadAction); // create button with Action
breadButton.setVerticalTextPosition(AbstractButton.BOTTOM); // position text
breadButton.setHorizontalTextPosition(SwingConstants.CENTER);
add(breadButton);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
TestBread mainPanel = new TestBread();
JFrame frame = new JFrame("TestBread");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
Our AbstractAction or "super" ActionListener
#SuppressWarnings("serial")
class BreadAction extends AbstractAction {
public BreadAction(String name, int mnemonic, Icon icon) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
putValue(LARGE_ICON_KEY, icon);
}
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("bread pressed");
}
}

How to change a JLabel with a button from another class?

I have two classes and a text file database, The JLabel in the first class, let's call it class1 automatically set it self to the number in the database. Now, in class2 I have this little JFrame and a text field and of course a button, the value I put in the text field overwrites the one in the database, but here's the problem. The label in the first class wont update while running, but if I restart it it will show me the value that I want.
How do I update it while the program is running?
I've tried to change the label in the buttonActionperformed in the other class but it gives me a NullPointException every time.
How do I fix this?
THE MAIN CLASS ( JUST THE JFRAME )
package BankrollG;
import java.awt.Graphics;
import javax.swing.JFrame;
public class BGbrain {
BGbody body = new BGbody();
JFrame Frame = new JFrame();
public BGbrain() {
Frame.setSize(body.width, body.height);
Frame.setTitle(body.title);
Frame.setResizable(false);
Frame.setDefaultCloseOperation(Frame.EXIT_ON_CLOSE);
Frame.add(body.panel);
Frame.setLocationRelativeTo(null);
Frame.setFocusable(true);
Frame.setVisible(true);
}
public static void main(String[] args ) {
new BGbrain();
}
}
Then you got the class with the components:
private JLabel bankroll_label
public BGbody(){
panel.setLayout(null);
windowComponents();
}
public void windowComponents() {
// Bankroll database access
try {
FileReader fr = new FileReader("Bankroll.txt");
BufferedReader br = new BufferedReader(fr);
set_bankroll = br.readLine();
} catch(IOException e) {
System.out.println("FEL MED LĂ„SNING AV DATABAS /// BGBODY");
}
}
}
THEN you got the JFrame class that I created with the netbeans function
private void AddcurrencyActionPerformed(java.awt.event.ActionEvent evt) {
String CBR = txt_bankroll.getText();
try {
FileWriter fw = new FileWriter("Bankroll.txt");
PrintWriter pw = new PrintWriter(fw);
pw.println(CBR);
pw.close();
} catch(IOException e) {
System.out.println("FEL MED INSKRIVNINGEN I DATABASEN");
}
}
Now, everything goes as plan, but I can't update my JLabel "bankroll_label" from the button class because it just returns nullpointsexceptions. The data is there, because the JLabel reads from the database but it wont update when changes has been made from the button class. So a getter setter method wont work because the value IS there but it wont update the JLabel.
I hope this made it easier to understand my problem.
It's ALOT more code, that dont have to do with this, I hope I simplified it at least some.
Your question is a specific example of a basic problem in programming in Java -- how to transfer information between classes. There are several ways to do this, one of the most elegant being giving to use a "model" class that holds your program's logic code and key data, having one class change the model's state by changing a text String that it holds. Then using a listener or observer pattern, have the model notify the other class that it has been changed so the other class can extract the new information, its new String from the model. While this is likely the best solution, it may be a bit of overkill and likely is above your current level of coding, so for you, I'm not going to recommend this.
Instead, I'm going to recommend a simpler less elegant solution, that you instead have one class call a setter method of the other to push the new String into it.
One problem we have as volunteer answerers here is that your question is hard to answer because it lacks critical code, making it hard for us to guess why your code is misbehaving, why specifically you're running into a NullPointerException (or NPE) when you try to run it. So all I can do is guess, but guess I will try nevertheless.
For simplicity's sake, let's call one class the, the one that holds the JLabel, the LabelClass and the other class the ButtonTextFieldClass.
One possible reason is that you've got a NullPointerException is because your ButtonTextFieldClass may have a LabelClass variable, but never initialized the variable, something like so:
// this guy is null because it is never initialized
private LabelClass labelClass;
A simple solution could be to try to initialize it like so:
private LabelClass labelClass = new LabelClass();
But this won't work because while it does create and assign a LabelClass instance, it's likely not the LabelClass instance that is visualized in the running GUI.
A better solution is to give the ButtonTextFieldClass a setter method that allows other classes to set the ButtonTextFieldClass with the proper LabelClass instance.
e.g.,
public void setLabelClass(LabelClass labelClass) {
this.labelClass = labelClass;
}
This way the code that sets up both classes can pass the visualized LabelClass to the first class, and it can call methods on it.
A simple example of LabelClass could look like so:
class LabelClass extends JPanel {
private JLabel label = new JLabel("");
public LabelClass() {
setBorder(BorderFactory.createTitledBorder("Label Panel"));
add(label);
}
public void setLabelText(String text) {
label.setText(text);
}
}
I have it extend JPanel because this way it gives me the freedom of placing it into a JFrame or JDialog or other JPanel as I see fit. Note that I've made the JLabel private and have given the class a public setter method, setLabelText(String text), that allows outside classes the ability to set the JLabel's text.
The ButtonTextFieldClass could look something like:
class ButtonTextFieldClass extends JPanel {
private JTextField textField = new JTextField(10);
private JButton button = new JButton(new ButtonAction("Send Text"));
private LabelClass labelClass;
public ButtonTextFieldClass() {
setBorder(BorderFactory.createTitledBorder("Button TextField Panel"));
add(textField);
add(button);
}
// here we allow other classes to set instances of our LabelClass
public void setLabelClass(LabelClass labelClass) {
this.labelClass = labelClass;
}
// ....
I've also given the button an AbstractAction in place of an ActionListener since it is like a super ActionListener on steroids. Inside of it, I'd get the text from the JTextField and then call the LabelClass's setter method (if the variable is not null) to set the label's text:
public void actionPerformed(ActionEvent e) {
String text = textField.getText();
if (labelClass != null) {
labelClass.setLabelText(text);
}
}
Then to set everything up, in another class I'd create instances of both LabelClass and ButtonTextFieldClass, and then "hook them up" by calling the setter method:
LabelClass labelClass = new LabelClass();
ButtonTextFieldClass buttonTextFieldClass = new ButtonTextFieldClass();
buttonTextFieldClass.setLabelClass(labelClass); // set our reference
The whole thing could look like so:
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class TransferData {
private static void createAndShowGui() {
LabelClass labelClass = new LabelClass();
ButtonTextFieldClass buttonTextFieldClass = new ButtonTextFieldClass();
buttonTextFieldClass.setLabelClass(labelClass); // set our reference
JPanel mainPanel = new JPanel(new GridLayout(0, 1));
mainPanel.add(buttonTextFieldClass);
mainPanel.add(labelClass);
JFrame frame = new JFrame("TransferData");
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 LabelClass extends JPanel {
private JLabel label = new JLabel("");
public LabelClass() {
setBorder(BorderFactory.createTitledBorder("Label Panel"));
add(label);
}
public void setLabelText(String text) {
label.setText(text);
}
}
class ButtonTextFieldClass extends JPanel {
private JTextField textField = new JTextField(10);
private JButton button = new JButton(new ButtonAction("Send Text"));
// one possible solution -- give this class a variable
// of the LabelClass -- but don't initialize the variable
// here, but rather do it in a setter
private LabelClass labelClass;
public ButtonTextFieldClass() {
setBorder(BorderFactory.createTitledBorder("Button TextField Panel"));
add(textField);
add(button);
}
// here we allow other classes to set instances of our LabelClass
public void setLabelClass(LabelClass labelClass) {
this.labelClass = labelClass;
}
// an AbstractAction is like a "super" ActionListener
private class ButtonAction extends AbstractAction {
public ButtonAction(String name) {
super(name); // set the button's text and actionCommand
int mnemonic = (int) name.charAt(0); // get first char
putValue(MNEMONIC_KEY, mnemonic); // set mnemonic
}
#Override
public void actionPerformed(ActionEvent e) {
String text = textField.getText();
if (labelClass != null) {
labelClass.setLabelText(text);
}
}
}
}
For simplicity's sake, I've displayed both JPanels within the same GUI, but it could work just as well if one JPanel were in one JFrame and the other within a JDialog.

Categories