Cannot set variable by listener - java

I'm beginning with GUI and listeners. I want to choose and set file from pc into the "File zvolenysubor" in class Hlavna by another class implementing ActionListener.
I can choose file in the listener's actionPerformed method and set it into "File subor" but I fail in saving it into the "File zvolenysubor" in my main (and all of my ideas how to do it failed too).
What should I change/add there please?
Here are my classes:
public class Hlavna {
public static void main(String[] args) {
File zvolenysubor = null;
JFrame frame = new JFrame("ABCDE");
JButton vybersuboru = new JButton("vyber");
vybersuboru.setBounds(220, 15, 200, 20);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(640, 480);
frame.add(vybersuboru);
frame.setLayout(null);
VyberListener list1 = new VyberListener(zvolenysubor);
vybersuboru.addActionListener(list1);
vybersuboru.setText("vyber subor");
}
}
public class VyberListener implements ActionListener {
private File subor;
public VyberListener(File subor){
this.subor = subor;
}
#Override
public void actionPerformed(ActionEvent e) {
JFileChooser chooser = new JFileChooser();
System.out.println("lol");
FileNameExtensionFilter filter = new FileNameExtensionFilter("JPG & GIF Images", "jpg", "gif");
chooser.setFileFilter(filter);
chooser.showOpenDialog(null);
subor = chooser.getSelectedFile();
System.out.println(subor.getAbsolutePath());
}
}

Not really sure what you're asking here. Java passes method arguments by value as opposed to reference, so the File parameter you're supplying to the constructor of VyberListener is only updated in the VyberListener class by the actionPerformed method, not the reference in your main method. What is it you're trying to accomplish here?
If you're trying to update "File zvolenysubor" in your main method, it may be worthwhile making your "File subor" in your VyberListener class public, so that it can be accessed by the main method.
Update
To minimise the amount of chatter in the comments below, I'll try and summarise. Although Java supports pass by reference, it's actually only passing pointers by reference. Thus in your example, you pass a null object reference (subor) to your ActionListener, which is then overwritten in the actionPerformed method:
subor = chooser.getSelectedFile();
Thus your File variable "zvolenysubor" is never updated. In order to update fields in your Hlavna class, I recommend using the following "Container" pattern:
public class Hlavna {
public static void main(String[] args) {
// New "FileReference" container instance
FileReference zvolenysubor = new FileReference();
JFrame frame = new JFrame("ABCDE");
JButton vybersuboru = new JButton("vyber");
vybersuboru.setBounds(220, 15, 200, 20);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(640, 480);
frame.add(vybersuboru);
frame.setLayout(null);
VyberListener list1 = new VyberListener(zvolenysubor);
vybersuboru.addActionListener(list1);
// Retrieves the updated File instance
File updatedFile = zvolenysubor.getFile();
}
}
public class VyberListener implements ActionListener {
private FileReference subor;
public VyberListener(FileReference subor){
this.subor = subor;
}
#Override
public void actionPerformed(ActionEvent e) {
JFileChooser chooser = new JFileChooser();
FileNameExtensionFilter filter = new FileNameExtensionFilter("JPG & GIF Images", "jpg", "gif");
chooser.setFileFilter(filter);
chooser.showOpenDialog(null);
subor.setFile(chooser.getSelectedFile());
}
}
// FileReference container class allows the file reference to be updated by the ActionListener
// without re-initialising the object reference
public class FileReference {
private File _file;
public void setFile(File file) {
_file = file;
}
public File getFile() {
return _file;
}
}

Related

Change value of public variable in Java, used by multiple frames

I have two frames in NetBeans 9.0 as frame1.java, frame2.javaand the main class as main.java.
If I declare a public variable in frame1.java as
public String stringName;
and a function fn() which gives the value of stringName in frame1as say "abcd".
When I write this in frame2,
frame1 fm = new frame1();
String str = frame1.stringName;
System.out.print(str);
I get the output as null. But what I require is "abcd".
What am I doing wrong, and what should it be?
Thanks for help!
Edit:
I have linked frame1 and frame2 such that the GUI from frame1 leads to frame2, and so does the value.
Edit 2
The process goes like this:
GUI of frame1 is visible >> based on user's input, function fn() stores the value, say "abcd" in stringName >> a button click in frame1 leads to frame2>> variable str gets the value from stringName >> System.out.print(str) outputs the value as null .
CODE
frame1:
public class frame1 extends javax.swing.JFrame {
public String stringName;
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt){
stringName = jTextField1.getText(); // gets a not null value
}
}}
frame2:
public class frame2 extends javax.swing.JFrame {
frame1 fm = new frame1();
String str = frame1.stringName;
System.out.print(str); //outputs a null value
}
The point ist that you are crating a new Instance (frame1, fm) in your class frame2. So the value from the string in this new Instance is null. You need a reference to your old Instance which you maybe have initialised in your main method?
Something like that:
String str = myOldInstance.stringName;
But you should create getter an setter and make your var private.
But to help you exactly we need more Code.
in this case the best is Listener pattern.
Create interface of listener, which will inform about change text. In class - target of this information - create instance of this listener and return that. In class - source of information - set listener and put on field.
When you want inform of change text, you fire method of listener, and on seconde frame will execute implementation of method.
Below example - I fire on button click.
Any way, field should be private, and add getter and setter. Public fields are bad.
Main class
public class App {
public static void main(String[] args) {
Frame1 f1=new Frame1();
Frame2 f2=new Frame2();
TextListener textListener = f2.getListener();
f1.setListener(textListener);
}
}
Listener
public interface TextListener {
public void onTextPropagate(String text);
}
Frame classes
public class Frame1 extends JFrame{
private TextListener listener;
JButton button;
public Frame1() {
super("Frame1");
setBounds(200, 200, 400, 600);
button=new JButton("Action");
button.setBounds(100, 200, 200, 100);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(listener!=null) {
String text = UUID.randomUUID().toString();
System.out.println("On Frame1:\t"+text);
listener.onTextPropagate(text);
}
}
});
this.add(button);
setVisible(true);
}
public void setListener(TextListener listener) {
this.listener=listener;
}
}
public class Frame2 extends JFrame{
public Frame2() {
super("Frame2");
setBounds(100, 100, 200, 400);
setVisible(true);
}
public TextListener getListener() {
return new TextListener() {
#Override
public void onTextPropagate(String text) {
reactOnChangeText(text);
}
};
}
private void reactOnChangeText(String text) {
System.out.println("On Frame2:\t"+text);
}
}

How to access another object from within a listener in Java

I have a listener on one of the elements of the menu class GraphMenu() in my program that that needs to call a method of an existing object created outside that class and I can't seem to find a way to implement this.
I'm defining the method of the panel I need to call in the GraphPanel() class:
public class GraphPanel extends JPanel {
private JLabel textLabel, graphicLabel;
private JTextArea textArea;
private JPanel graphPanel;
public void appendTextArea(String s) {
textArea.append(s + '\n');
}
The listener of the GraphMenu() I need to call that method in is:
public class GraphMenu {
...
// Add the action listeners that identify the code to execute when the options are selected.
menuItemLoad.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
final JFileChooser fc = new JFileChooser();
// you can set the directory with the setCurrentDirectory method.
int returnVal = fc.showOpenDialog(null);
if (returnVal == JFileChooser.APPROVE_OPTION) {
// User has selected to open the file.
File file = fc.getSelectedFile();
try {
// Open the selected file
BufferedReader reader = new BufferedReader(new FileReader(file));
// Output the contents to the console.
String nextLine = reader.readLine();
while ( nextLine != null ) {
panel.appendTextArea(nextLine);
System.out.println(nextLine);
nextLine = reader.readLine();
}
reader.close();
} catch (IOException e1) {
System.err.println("Error while reading the file");
}
};
}
});
...
Is there a way I can call the appendTextArea() on the panel object as in the example above?
I'm creating the two objects of class GraphPanel() and GraphMenu() in the main function:
GraphPanel panel = new GraphPanel();
frame.getContentPane().add(panel);
GraphMenu menu = new GraphMenu();
frame.setJMenuBar(menu.setupMenu());

Accessing data from another class which reads values

Ok, so here is a problem: I have main class which generates a window and two buttons:
...
public MainWindow()
{
...
b_read.addActionListener(new ReadStudents());
b_open_all.addActionListener(new OpenStudents());
...
In ReadStudents.java class I load data from a file with JFileChooser and print it on the screen. Sample of code thats load file:
#Override
public void actionPerformed(ActionEvent e) {
...
JFileChooser fc = new JFileChooser(".");
...
int rez = fc.showOpenDialog(fc);
if (rez == JFileChooser.APPROVE_OPTION) {
file = fc.getSelectedFile();
...
So now in my ReadStudents.java class variable "file" has my loaded information.
How do i pass this variable with containing information in it to a class that prints Students on the screen (second button OpenStudents.java) ?
Edit:1) I can not initialize an object of ReadStudents.java in OpenStudents.java class because in the new object variable "file" will be empty. Something is loaded to a "file" only when a button b_read is pressed.
One option would be to implement the action listener on your MainWindow class and the call a method in the ReadStudents/OpenStudents that return the list of files.
For example:
/**
* Main window class.
*/
public static void main(String args[]) {
JFrame mainFrame = new JFrame();
mainFrame.setLayout(new BorderLayout());
mainFrame.setSize(100, 100);
final StudentReader student = new StudentReader();
JButton button = new JButton("Click Me");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// Make the call here. Take note!
// Look at the return type!
List<String> strings = student.fileNames();
for (String s : strings) {
System.out.println(s);
}
}
});
mainFrame.add(button);
mainFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
mainFrame.setVisible(true);
}
public class StudentReader {
public List<String> fileNames() {
// Do your magic here :)
// Open a dialog. Get the files.
// Return it as a list
return Arrays.asList(new String[]{"Filename"});
}
}
I Hope this helps!

Why is my output null every time?

Hello I have a class that opens a JFrame and takes in a text. But when I try getting the text it says its null.
Everytime I click the button I want the System.out to print the text I entered in the textArea.
This is my first class :
public class FileReader {
FileBrowser x = new FileBrowser();
private String filePath = x.filePath;
public String getFilePath(){
return this.filePath;
}
public static void main(String[] args) {
FileReader x = new FileReader();
if(x.getFilePath() == null){
System.out.println("String is null.");
}
else
{
System.out.println(x.getFilePath());
}
}
}
This is a JFrame that takes in the input and stores it in a static String.
/*
* This class is used to read the location
* of the file that the user.
*/
import java.awt.*;
import java.awt.event.*;
import java.awt.event.*;
import javax.swing.*;
public class FileBrowser extends JFrame{
private JTextArea textArea;
private JButton button;
public static String filePath;
public FileBrowser(){
super("Enter file path to add");
setLayout(new BorderLayout());
this.textArea = new JTextArea();
this.button = new JButton("Add file");
add(this.textArea, BorderLayout.CENTER);
add(this.button, BorderLayout.SOUTH);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(300, 100);
setVisible(true);
this.button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
filePath = new String(textArea.getText());
System.exit(0);
}
});
}
}
But everytime I run these programs I get
String is null.
You are mistaken by the way how JFrames work. A JFrame does not stall the execution of the code until it is closed. So, basically, your code creates a JFrame and then grabs the filePath variable in that object, before the user could have possibly specified a file.
So, to solve this, move the code that outputs the filepath to stdout to the ActionListener you have. Get rid of the System.exit() call, and use dispose() instead.
Update: You should have this code for the ActionListener:
this.button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
filePath = new String(textArea.getText());
if(filePath == null){
System.out.println("String is null.");
}
else
{
System.out.println(filePath);
}
dispose();
}
});
And as main method:
public static void main(String[] args)
{
FileBrowser x = new FileBrowser();
}
Your main does not wait until the user has specified a text in the textArea. You could prevent this behaviour by looping until the text in the textArea is set or you could place the logic of the main function into the ActionListener to handle the event.
Following the second way the main function only creates a new FileBrowser object.

Swing jfilechooser blocking other frames after passing null

I want my jfilechooser to display without blocking parent but i tried everything and still it is blocking parent. Any Solution....
public class main_class {
public static void main(String[] args) {
JFrame parent_frame = new JFrame("PARENT");
if (parent_frame != null) {
parent_frame.setBounds(50, 50, 500, 500);
parent_frame.setVisible(true);
parent_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JFileChooser chooser = new JFileChooser();
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int returnVal = chooser.showDialog(null, "Ok");
}
}
}
By default, showDialog will use a modal dialog.
JFileChooser is simply based on a JComponent, so, so long as you don't mind that your code won't block, you could add the JFileChooser to a frame/dialog that you can yourself.

Categories