java pass object from JFrame to JPanel - java

I am developing a standalone application, in Java using NetBeans, that gets and sends data via Serial Port. I am using a great API for Serial communication called java simple serial connector http://code.google.com/p/java-simple-serial-connector/
Please download the following NetBeans project that I created:
http://netload.in/dateiN9xmwRtn19.htm
Even if you do not have netbeans you can still view the code.
The above is a small example project that I made to explain what I wish to accomplish. The example contains a JFrame that contains the main method. This JFrame contains 2 panels: a Panel with navigation buttons, and a Panel that displays Panel 1 and Panel 2 using CardLayout.
In the JFrame I have a method that gets port names list using the getPortNames() method of the jssc API. My question is, how do I pass these port names String values from JFrame to my Panel 1, without using the following since it will not work:
MyJFrame myjframe = new MyJFrame();
myjframe.getPortNames();
Hovercraft Full Of Eels
Once again thank you very much for your explanation, it is worth gold. I now realize that my problem is NetBeans rather than Java. I am not familiar with it enough but I would still prefer to use it due to the size and complexity of my project. I have uploaded 2 more screenshots below, that show how I tried to pass the "this" reference of the JFrame object to my JPanel object in NetBeans. As you can see in the MyJFrame.java screenshot, NetBeans has underlined "this" reference as an error. Would you please be able to help me with this problem? Also, in the first sentence of your explanation you mention that the serial port methods should be in a separate class, not in JFrame, since they are non-GUI methods. I fully agree with you and I would prefer to do it that way since it is the correct object-oriented approach. But doing it that way, I am once again facing the same problem in NetBeans. How do I now pass the object reference from SerialPorts.java class to JFrame, JPanel etc in a way so that I am not creating a new SerialPorts object all the time, remember I need the connection to stay open all the time (ex. without using SerialPorts sp = new SerialPorts();). Thank you so so so much for your help.
Adding "this" in code customizer for Panel 1
MyJFrame.java - editor underlines reference "this" as error

I wonder if you should have the port names held by a non-GUI model class and obtained from it rather than from the "JFrame", but regardless your question is a specific example of a more of a general question: how do you pass information from one GUI object to another, and that can be generalized further to: how do you pass information from one object to another.
The simple answer is to have one object call a method on the other, which is what you've tried, and which is what should work, but the problem with your attempt is that you're calling it on the wrong object. You have a JFrame object that has already been constructed, that is visible, and that holds the information you need, and that is the object which you should be calling your method on, not a new JFrame object. Sure the new object is built from the same class, but understand that it is a completely different object from the one that's displayed which is the one you want.
So now your problem boils down to this -- how do I get a reference to the visualized JFrame into another object? There are many ways to do this, but the easiest way to do this is to probably pass a reference from one class to the other via a constructor or method parameter.
...
So for instance, say you've got a class called FooFrame that extends JFrame, and it holds a FooPanel object that extends JPanel, and suppose you want the FooPanel object to call the someMethod() method of FooFrame:
public class FooFrame extends JFrame {
public String someMethod() {
return myTextField .getText();
}
}
You could have FooPanel create a new FooFrame object and call this method as you're trying to do:
class FooPanel extends JPanel {
public void otherMethod() {
FooFrame fooFrame = new FooFrame();
fooFrame.someMethod();
}
}
But then you run into the same problem you're running into above. The FooFrame object created here is not the one being displayed, and so the contents of the JTextField will be empty and not very helpful. The solution I'm suggesting is that you pass a reference from the original JFrame into the JPanel via a constructor parameter like so:
class FooPanel extends JPanel {
private FooFrame fooFrame;
// constructor accepts a reference to a FooFrame object
public FooPanel(FooFrame fooFrame) {
this.fooFrame = fooFrame; // and sets its field with it
}
public void otherMethod() {
// no longer needed!
// FooFrame fooFrame = new FooFrame();
// now method is called on the right object!
fooFrame.someMethod();
}
}
Then you can create your FooPanel object in FooFrame and pass the FooFrame object (this) into it.
public class FooFrame extends JFrame {
private JTextField myTextField = new JTextField(10);
private FooPanel fooPanel;
public FooFrame() {
// the current FooFrame object is this!
fooPanel = new FooPanel(this);
add(fooPanel);
}
public String someMethod() {
return myTextField .getText();
}
}

Related

Get which Jframe opened another Jframe

Say I have a JFrame called childJframe.
If I create a new childJFrame from two different JFrames. How can I get which particular JFrame created the childJFrame.
Thus:
public class myPage1 extends javax.swing.JFrame{
// on a Button clicked
childJFrame cjf = new childJFrame();
cjf.setVisible(true);
}
And the Second class is
public class myPage2 extends javax.swing.JFrame{
// on a Button clicked
childJFrame cjf = new childJFrame();
cjf.setVisible(true);
}
How can I find out if cjf is an instance of myPage1 or myPage2?
The Window class, which JFrame descends from, has a getOwner() method that will return the "owner" Window for any child windows.
But having said that, child windows should be JDialogs, not JFrames as your application should have one and only one JFrame, and I believe that JFrames don't have owners, so that this method may return null. If you need to change "views" within the JFrame, use a CardLayout, and if you need to display child windows, use dialog windows such as JDialogs and JOptionPanes. Please read: The Use of Multiple JFrames, Good/Bad Practice?, for more on this.
But having said this, I do have to wonder if your question may in fact be an XY Problem where you ask "how do I fix this code" when the real solution is to use a different (read -- more "object oriented") approach entirely.
If your child windows must really be JFrame instances (I suppose ChildJFrame extends JFrame), I think the simplest solution consists in keeping track of the parent JFrame in the ChildJFrame instance. Since ChildJFrame is a custom class of yours, this is easy:
Add a JFrame (or Frame or Window) attribute to your ChildJFrame class;
Add to ChildJFrame a constructor that takes a parameter that will be assigned to the above attribute;
When you create a ChildJFrame instance from one of your JFrame-derived classes, just add this as a parameter.
Then you have everything you need to interact with the parent JFrame.

Communictating between classes using Jpanel, repaint() method

I have a class "GUI" that extends JPanel. I have another class "Buttons" that extends JFrame. I'm trying to have the JFrame class call a method "clearScreen()" in the JPanel class when the when a JButton "clearB" is pushed on the JFrame.
The only way I could make this work was by building the object for the JPanel class "GUI" right in the actionlistener for the JButton:
clearB.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent event){
GUI g = new GUI();
g.clearScreen();
}
}
);
But then when I called the method clearScreen(), which looks like this:
public void clearScreen(){
xs.clear();
ys.clear();
count = 0;
repaint();
}
NOTHING HAPPENED. I'm guessing it's because the repaint() method wasn't working for some reason unknown to me.
Someone PLEASE show me an easier, working way of doing what I'm trying to accomplish here.
Thanks! :D
The reason that your ActionListener isn't working is because the GUI object that you create in there is a new GUI object, one that is completely unrelated to the GUI object that is displayed, and so calling the clearScreen() method on the non-displayed GUI instance will have no effect on the displayed GUI instance.
The solution is for your Buttons class to hold a valid reference to the visualized GUI object and call methods on this reference. The reference can be passed via a setter method or constructor parameter.
i.e.,
public class Buttons {
private GUI gui;
public Buttons (GUI gui) {
this.gui = gui;
}
// in some ActionListener code...
gui.someMethod();
}
A couple of comments:
It is unusual that you should have to have a class that extends JFrame. Myself, I try to avoid doing this unless necessary, but rather usually create my JFrames from the JFrame class itself, and only when needed.
I'm a little surprised that your main window class doesn't already have a GUI variable, since it likely displays the GUI instance.

java: how can i pass a variable from the starter JFrame to the last without having to pass it through all JFrames?

I have this problem: I have an ArrayList that contains a few items that I want to use in a particular frame, the problem is that the array list gets full by initializing it in the main class of my project. In this class I also launch my starting frame that is chained with other frames (login frame -> middle frame --> last frame). I want to carry this ArrayList without having to carry it on through all frames and get it directly usable from main --> last frame. How can I do this?
EDIT
Wat I did it was like first frame start with this ArrayList as parameter:
Jframe jf = new LoginFrame(arraylistvariable,"Login Window");
Then in all ActionListener calls on the buttons that create new frames, disposing old ones, I set it like:
Jframe jo = new MiddleFrame(arraylistvariable,"Middle Window");
Passing this variable all over the frames but I want this to be like called only by the frame that needs this, because login frame doesn't need this variable. However, it is necessary to start the program by the login frame.
"However, it is necessary to start the program by the login frame."
No it's not.
public class MiddleFrame() {
private LoginFrame;
}
...
public static void main(String[] args){
new MiddleFrame();
}
Make the middle frame not visible upon instantiation, but make the LoginFrame visible. If the login is successfful, but make the MiddleFrame visible.
Note You don't need to use to many frame. Make use of JDialogs. See this answer for How to make a Login with a JDialog
one from the easiest way it to pass it/them trough system properties
You might want to create some class like ArrayListVariableProviderService and make it accessible either to all classes (JFrames) or via static call.
This can act as a container to many things, yet it'll abstract out all peculiarities.
Good luck.

Passing variables within several JFrames and classes

sorry guys, but I got confused after many hours sitting ang writting the code.
Situation:
I have two JFrames. These are different Java classes - one of them is the FirstGUI, from which we can call the other JFrame called SecondGUI. OK - that's clear.
I also have one class called Processor in which i have specific methods like "connectToPort" or "disconnectFromPort".
Also, in the FirstGUI (which has the main method) I'm creating SecondGUI object (and set setVisible to false) and Processor object with FirstGUI and SecondGUI as parameters.
Problem:
From the FirstGUI in I want to call out SecondGUI (by setVisible to true) - OK, done. But what about calling out the created at the beginning Processor object from the SecondGUI JFrame? It's important to call the SAME object, because Processor methods can for example set text in the FirstGUI JFrame.JTextPane component, and add items to JComboBox of the SecondGUI.
I don't know how to solve this, I'm always getting NullPointerException.
EDIT:
I want to add that I can't pass the Processor object as an argument while creating SecondGUI, because Second GUI is created earlier and it is an argument while creating Processor... That's the problem.
When constructing the second GUI (child), the initiating class (FirstGUI) can pass self in constructor, and also retain the reference to the constructed object. Now both GUIs have the reference to each other:
class F1 extends JFrame {
F2 child;
void createF2() {
child = new F2(this);
child.setVisible(true);
}
}
class F2 extends JFrame {
final F1 parent;
F2(F1 parent) { this.parent = parent; };
}
If you've searched out your problem or for similar problems on this site, you'll know that the most common recommendation is not to use multiple JFrames, that it is suggestive of a bad design. Better to either swap views with a CardLayout or use JDialogs of the appropriate modality.
As for your question, having one class pass information dynamically to another class, there are two main options depending on program structure.
If one class is in a modal JDialog, then the first class can pull information from the second modal class by calling appropriate getter methods after the second window is no longer visible.
If one class is displayed non-modally, then you'll want to use some type of listener such as a PropertyChangeListener to have the listening class be notified by the observed class when state changes occur.
Edit
Regarding:
From the FirstGUI in I want to call out SecondGUI (by setVisible to true) - OK, done. But what about calling out the created at the beginning Processor object from the SecondGUI JFrame? It's important to call the SAME object, because Processor methods can for example set text in the FirstGUI JFrame.JTextPane component, and add items to JComboBox of the SecondGUI.
Audrius gives you an answer for that. 1+ up-vote given to his answer.
I don't know how to solve this, I'm always getting NullPointerException.
If you get a NPE, should carefully inspect the line that throws the NPE to see which variable is null and then trace back in your code to see why. If your still stuck on a NPE and need our help, then you'll want to show pertinent code and give us more detail on the problem including noting which variable is null and why you think that it shouldn't be null.
EDIT: I want to add that I can't pass the Processor object as an argument while creating SecondGUI, because Second GUI is created earlier and it is an argument while creating Processor... That's the problem.
This is a non-issue. Since the dependent window is displayed dynamically, you can always pass a reference just prior to displaying it using a setter method.

Accessing Swing components of another class

I have two classes gameWindow and gameEngine. The Main method is in gameWindow class & so is the swing GUI code. Now, I want to access the swing components in gameEngine. How to do that? I always get the cannot find symbol error when I try it normally. I've tried making the components public but with no luck.
Also, I tried creating a instance of gameWindow but it too, didn't help. It compiled without any error but I got a BIG runtime error(which I can't even see, the command prompt gets scrolled to it's limit).
RELP!!
P.S.: I don't think the posting the code here will help.
In order to access the components of gameWindow in gameEngine you need a reference to it. So I assume that GameWindow class creates the instance of GameEngine. Then you can do something like this:
public class GameEngine{
GameWindow window;
public GameEngine(GameWindow gm){
window = gm;
}
//rest of your code
}
public class GameWindow(){
//At the point where you create the GameEngine
GameEngine ge = new GameEngine(this);
//rest of your code
}
Now GameEngine has a reference to the GameWindow that it can use.
Having said that, I would advise that you consider a different design. Having GameEngine directly access the GameWindow sounds as if the wrong classes are responsible for the wrong things. Maybe you might try looking at using some sort of Observer such that the GameWindow looks for changes in the GameEngine then accesses the updates and modifies the view accordingly. So the GameEngine does not have to access the swing components of GameWindow.
Pass a reference to gameEngine in the contructor or use a getter/setter type method.
For example, in gameWindow, when you create the gameEngine class, have a constructor that takes a gameWindow variable.
gameEngine:
gameWindow theMainWindow = null;
public gameEngine(gameWindow mainWindow)
{
theMainWindow = mainWindow;
}
Vincent's answer is correct, but involves instantiating GameWindow which the post said gives an error. I would advise redirecting your error stack trace to a file, reading it and troubleshooting your runtime error, then following his instructions.

Categories

Resources