Accessing Swing components of another class - java

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.

Related

2D Game not repainting

I checked the other questions and couldn't find one with the same case as me so here's my question.
I am making a 2 player stick fighting game that you can play on the same computer using different keys. Everything's fine but when I try to move the oval on the screen with the keys, it's not moving.
Here's the code for my first class - http://pastebin.com/wA0JXdzr
second class - http://pastebin.com/ArByyirt
I think I need to call repaint in my second class in the gameloop, but it's saying that it can't make a static reference to it.
You are trying to call a non static method directly from another class which is not legal in java. The paint() method in your first class is the non-static method. You were able to use the variables stickx2 and such because they are static as defined in your first class.
Thus, I suggest you create an object of stickFrame() in the gameLoop class and copy all your code in your stickframe main method and put it in your gameLoop main method. It is highly not recommended that you have two main methods.
Declare a Stick Frame variable below your Serialization ID.
StickFrame s;
Then instantiate it in your gameLoop constructor
s = new StickFrame();
Now we need to fix the repaint from another class problem.
To do this we need a method in the gameLoop Class.
public void repaintStickFrame()
{
s.repaint();
}
Then call it by
s.repaintStickFrame() in your loop.
or you can just call
s.repaint();//place in loop
Heres a link to a question that is similar to yours and has solutions as well
Calling repaint from another class JFrame
Heres a link that explains how you can call an objects method once you've created one (Like we did above, which allowed us to call the repaint() method from a different class):
https://docs.oracle.com/javase/tutorial/java/javaOO/usingobject.html

Instead of getting two similar JFrames, I get one whith double component

I created a JFrame with buttons, labels and texts and I want to show it two times when I execute the main program, so I did like that:
import java.net.SocketException;
public class Main {
public static void main(String[] args) throws SocketException {
new MyFrame("client1");
new MyFrame("client2");
}
}
The result: I get two frames: one with the component of the other one inside, and one empty.
How to resolve this issue?
You are using static instance fields with your MyFrame for your components
A component can only reside within a single container, the moment you create your second frame, the static components are removed from the first container before been added to the second.
The solution, don't do this, ever...
I assume you are using static because you want to access these fields from another class, in that case, you should appropriate getters in the MyFrame class and pass a reference of it to those classes that need it.
Alternatively, you could establish a series of observers who monitor for changes and take appropriate action, this helps to decouple the code.
Personally, if you need to modify the MyFrame instances in some way, I'd provide setter methods that update your components instead, as I don't like exposing UI elements without good reason, to much opportunity for others to mess with them in appropriately

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 ActionListener in another Class

I am trying to build a small notepad application using the Java Swing library. I have a main function which calls a constructor of JFrame (NotepadClass). In this NotepadClass I have a MenuDesigner class something like this:
this.setJMenuBar(new MenuDesigner());
The MenuDesigner class extends JMenuBar which calls actionListener (MenuActionListener) which is written in another class.
Now my question is: If I click on "new" menuItem, the title which is in NotepadClass should change. How do I access a class that is two levels up?
Which concept of Java should I use to accomplish this?
use Swing Action instead of ActionListener, this API is designed for your purpose
post an SSCCE demonstrated your issue, just about JFrame with JMenuBar, JMenu and one, two JMenuItem(s), noting else
Without seeing your code it's difficult to give a definitive answer, but one of the reasons to write a separate class to build your menu is that you can pass instances to the class.
this.setJMenuBar(new MenuDesigner(notepadClass));
This is one reason why it's good to have a model class or classes when you're building a GUI.
You can pass an instance of the highest level model class to all of your GUI components, and each component can get or set the parts of the model class that they represent.
You could pass down the NotepadClass in the constructors and provide a method to change the title.
Another option is to build the ActionListener inside the NotepadClass or let NotepadClass itself implement the Actionlistener interface so you can access the variables or methods.
Why is your actionListener for your menu in another class?
You could create a new class that implements ActionListener in which you can add you own logic. This way you can reuse it in another file.
Also, you should probably de-couple your MenuDesigner class by moving it into its own file.

java pass object from JFrame to JPanel

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();
}
}

Categories

Resources