Communication between already existing classes - java

I am sorry if this question seems pretty basic and there is already an answer for that, but unless I make it into a proper question, google won't find it.
I have a main class that is a JFrame(there is and will be only one object, let's call it "main"), it creates and calls another JFrame class(let's call it window2), however, I still need this window2 to call methods from the already existing main class. Normally window2 would have something like Main mainMenu = new Main();.
But this obviously creates a new object of main, I still want to refer to the already existing object and get information from it.

Dependency Injection. The answer depends on whether your Main class is static, but let's assume it is not:
Create a Main reference in Window2: Main main;
Create a method in Window2: public void injectMainInstance(Main main){this.main=main}
In Main you have the Window2 instance window2. Call window2.injectMainInstance(this);
You should be good to go now in Window2 with main.mainMethodTBUsed();

Related

How to correctly implement communication between Java classes

I'm a beginner in Java programming and I'm currently working on an app with more complex class structure and a GUI. This might be a stupid questions, but it is very hard to google, so I'm asking here.
I have a main class, looking like this:
package app;
public class App {
private FirstClass fc;
private SecondClass sc;
public App () {
fc = new FirstClass ();
sc = new SecondClass ();
// ... code continues ...
}
}
Say the SecondClass is defined outside of this .java file (like GUI forms are). Is there a way for me to access the "fc" instance (or other member variables of the App instance) from the "sc" instance (without passing the "this" pointer)? Something like:
class SecondClass {
public void someMethod() {
getWhoeverCreatedThisInstance().fc.getSomeData();
// ... code continues ...
}
}
And if not, what am I doing wrong? Should I design this differently? Maybe setting the "fc" as static? But what if I want more of my app's classes to communicate with each other, should I make them all static? What would be the point of having something non-static then? I could pass the "this" pointer of "App" or "fc" instance in the constructor of "SecondClass", but that solution just seems non-elegant when the number of classes that need this behavior rises.
Any ideas? Thanks in advance!
My suggestion is to implement a callback system with interfaces. Each of your classes communicating with each other should implement these.
The classes should Register to the creating class.
Then they can call a method in the creating class which invokes the interface method of each registered class and passed the data this way.
This SO answer might help
https://stackoverflow.com/a/18279545
If you want to develop GUI applications, you should really get into the basic concepts. This can be very time-consuming, but it is necessary, otherwise you will encouter strange behaviour. I will just give you a basic understanding to answer your question.
You think of simple console applications, where you usually have a single thread and passing around objects is valid. With multiple threads, this is fatal, even with static variables. Each variable or object can be modified concurrently and the other thread may not be able to 'see' the changes in time. This is a complex matter, since there are also caches and separate stacks for each thread. In short, fc may not always be synchronized in App and sc, therefore reads and writes may be inconsistent.
What to do now? Learn the concepts of GUI programming. Often you do not even have to share objects for simple things. If a GUI control triggers an action, use a Listener, look here. If you want to access a database for example, then just make a new connection object for each request or button click, whatever. This is simple to start, add complexity later.
A simple variant to share objects is to use the synchronized keyword, which ensures that a method or a field is only accessed by one thread at a time. Here is an example. Also look at thread-safe data structures provided by Java (java.util.concurrent).
For advanced purposes you would have a separate thread and you would connect them with Sockets to pass messages or data.

Generally what is put in the main method and what isn't? - java

Beginner just starting out
.can i write entirety of code outside of main and still run? generally i'm asking what is "main" used for?
In theory you can just code everything in main and in will work. However to make your code structured you probably want to code outside of main and call it from main.
The main Method is the start point for the VM of Java. So if you want to run your application, there has to be a main method. Not only Java has this concept, also other OOP-Programminglanguages like C,C++,C#. You can write code outside the main. but remember that the code can only be accessed if there is a way to it from the main Method, example functions.
The main method is where your system is able to call and start the program up. The main method is needed if you wish to run your program and make use of your other classes.
You can create your program inside the main method if you wish, but as your programs become more sophisticated, you are going to want to create other classes that are initialized and used in your main method.
For example, if you make two classes called "Suv" "Sedan", and make one more class called "Mechanic" - the class that will hold your main - you can initialize Suv and Sedan and you can call the methods you made in Suv and Sedan to do things like change the engine, or to change the color, etc.
If you are just learning java, then don't worry about it too much and just write your code in your main method.
Main is the entry point of any java application. The Java Virtual Machine starts up by loading a specified class and then invoking the method main in this specified class.
You can write your code in main method, or somewhere else and call that in the main method in the order in which you want to execute it.
The method main must be declared public, static, and void. Following is the reason for it:
public:- main is marked public so that it can be accessed from anywhere outside the scope of the class or broadly we can say outside the scope of project.
static:- It is marked static so that it can be called without any instance of the class. Without declaring main method static, your program will compile successfully but throw an error at run time.
void:- The keyword void is used with main to tell the JVM that the main method does not return any value. It is solely for the initiation of the application not for returning anything.
Following is the valid declaration of the main method:
public static void main(String[] args)
public static void main(String... args)

Passing Parameters in JavaFx

I have implemented a GUI using javafx in a class called "Gui" which extends apllication. I have a seperate class which handles the logic called "Logic". I want to pass an instance of "Logic" class to to "Gui" class. Is there anyway that I can create an instance of "Gui" class before calling "Application.launch()" in main method?
Not easily, and this is almost always the wrong way to approach this. In particular, you don't even know that the main(...) method will be invoked: in Java 8 a JavaFX application is launched by the JVM without (necessarily) calling main(...) at all.
You should really consider the start(...) method in your Application subclass as the equivalent of the main(...) method in a regular Java application; in other words, think of this as your application entry point and create the Logic instance there.

Can someone explain how to setText from a static using my example?

First I would like to say that I have only worked with java for 1 month now. This is probly a pretty simple question. I searched and the classic fruit example did not make any sense to me. I spent hours looking at it and trying to figure out how to apply this to make it work. It does not make any sense to me because everyone explains how to get and set a property with 2 lines of code and no structure statements. I would really appreciate a breakdown in how to talk to non-static from static.
I would like to setText in text box in my OBD2nerForm class from a separate and static class.
public class OBD2nerForm extends java.awt.Frame {
/** Creates new form OBD2nerForm */
public OBD2nerForm() {
initComponents();
} ....................................
public String setText(String text){
this.jFormattedTextField1.setText(text);
}
I think I have a static reference to this instance of the form defined here..
public class Status {
public static OBD2nerForm form = new OBD2nerForm();
it is called from my main like this
public class obd2ner {
public static void main(String[] args) throws IOException {
Status.form.main(args);
Then when I try to call it.. Status.form.getText gives me the initial values when the form is created. When I setText, it does not change the one on the screen.
I am just displaying this to keep it simple. There are many other parts going on. I have a static monitor on a serial port and I want it to grab the next data to be sent from the text box and then increment it.
I just don't understand how to use a getter and a setter on a non-static. It's not quite doing what I need it to do. It seems like I am seeing one instance on my screen and it is using a new instance to perform the getting and setting.
I tried this as per an answer I received, but it did not work...
public class OBD2nerForm extends java.awt.Frame {
String X = "";
//Trying out the runnable method of incrementing the code
public String getNewScannerValueRunnable(){
Runnable doWorkRunnable = new Runnable() {
#Override
public void run() {
Status.form.getNewRotatingValue()
;}
};
SwingUtilities.invokeAndWait(doWorkRunnable);
return X;
}
I could really use some other suggestions. i just don't understand what has to happen here.
Your form is being created fine, and there's just one reference to it, and it's ending up in that static variable. All is well up to that point.
There's a 'secret' of Swing you need to be aware of: You cannot (visibly) change the properties of GUI objects from any thread other than the Swing thread, aka the Event Dispatching Thread.
The trick to doing it anyway is to pass the property-changing code as a Runnable to either of SwingUtilities.invokeAndWait() or SwingUtilities.invokeLater().
EDIT:
OK, let's back up. Your form is AWT based, not Swing based, so I'm afraid my advice on using SwingUtilities would probably not have helped you, even if you had implemented it correctly. I'll try to give more specific hints this time.
You've created a class OBD2nerForm that's an AWT form. That class has a constructor which calls initComponents to set up some GUI components on the screen.
The class also has a method called setText that will put its argument text into one of the fields on the form. That method is an instance method, i.e. it's not "static", as you'd call it.
You have another class, Status with a class field form. The initializer for form calls the constructor for OBD2nerForm. That will create an instance of the form and store it in form; but I haven't seen a show() or setVisible() call being made to the form to actually display it.
Here are the first signs of trouble:
public class obd2ner {
public static void main(String[] args) throws IOException {
Status.form.main(args);
Class names (like obd2ner) should start with capital letters; but that's a matter of style and convention, it's not what's causing you problems. Following the conventions helps other people read and debug your code, though.
The bigger problem is obd2ner.main() calling your form's main(). That could be made to work, but it's usually a sign that you're doing something wrong.
While nothing stops you from coding static main methods into as many of your classes as you want, only one of those main's can be started from the outside, i.e. when you run your application. The first main is essentially the 'boss' method for your program.
The "first main" usually instantiates and initializes a few objects. In a non-GUI application, main() may then start up a loop or some other control structure, wherein it will then orchestrate the actions of the other objects. In a GUI application, main() will usually just instantiate and then show the GUI, and then end; once the GUI is visible, all further program activity is triggered by actions the user performs on the GUI.
Without seeing your code, I'm guessing that Obd2nerForm.main() also instantiates Obd2nerForm, and shows it. So you probably indeed have one instantiated but invisible form hanging off Status.form and another one instantiated, visible and referenced from some variable in Obd2nerForm. If you want to influence that GUI, you need to make a reference to that form accessible.
Probably the simplest would be:
In Obd2nerForm, declare a public static Obd2nerForm form, and in Obd2nerForm.main, right after you call the constructor, copy the reference to the form into that variable. From then on, you can access the form and its methods using e.g. Obd2nerForm.form.setText().
A reminder, though: You seem to have two main()s, and this needs fixing. All the stuff that should be done at the beginning of the app's lifetime needs to be in one of those mains, not several.
Finally, look at this method call:
Status.form.main(args);
That's the syntax for calling a method on a particular instance. But Obd2nerForm.main is a class method (what you call "static"), and so there isn't "a particular one" to call, it's always just the one that belongs to the class itself. That's why the syntax to call a class method is something like
Obd2nerForm.main(args);
The compiler lets you get away with the way you wrote it, but it's not how it's usually done, and indicates some confusion.
There... I hope that gets you a little further along. If you still have problems, please post a more complete code sample to PasteBin and I'll take a look!

Questions regarding Extending JFrame in a class?

Okay, I'm NOT a Java noob, it just so happens that I've forgotten a tad bit about core Java while I was learning more fun stuff like MySQL, Servlets, Java EE, JDBC etc etc; so don't frame your answers as if I were a beginner. Now the question.....
I'm writing a class (lets say ThisIsAJFrameExtendingClass) which extends JFrame, and to minimize confusion with my overall project, I also want to park some other utility methods in ThisIsAJFrameExtendingClass. I intend this class (ThisIsAJFrameExtendingClass) to seek certain inputs from the user following which; commit suicide (ie dispose()). So, my question is, how can I independently use the utility methods inside the class without any JFrame popping up on the user screen.
I'ld like a solution with the help of multiple constructors inside the ThisIsAJFrameExtendingClass class, where, invoking the argument-less constructor return JFrame and the second constructor with a boolean argument gives access to the utility methods.
[UPDATE]
Ohh.... I just had a thought, the utility method has a return type of ArrayList so, assuming the utility method is called utilMethod() then:
ArrayList<String> pring = new ThisIsAJFrameExtendingClass().utilMethod();
will the above code output any JFrame?
You could make the utility methods static, in which case they can be invoked using ThisIsAJFrameExtendingClass.<method name> without creating an instance.
The stuff about constructors doesn't really make sense to me. A class's constructor always returns an instance of that class. It can't return "something else" because of a parameter you pass in.
[Edited to respond to the question's Update]:
new ThisIsAJFrameExtendingClass() will create an instance of your class, running its constructor (and the default constructor of all superclasses). This may allocate other resources (such as other Swing components or whatever) that each constructor in the inheritance tree requires. So a JFrame is created, but if you only call utilMethod() and never hang on to the reference to the frame, it will be garbage collected and its resources freed at some point in the future.
Creating a JFrame instance to call a single utility method on it isn't a particularly efficient way to go about things, but it won't cause any problems. (As Chad says, by default a JFrame isn't visible, so users won't see anything if you're using it in "util" mode).
As to returning an ArrayList, as a general rule when using collections, you should return the highest level interface that makes sense rather than a concrete class. So in this case, consider returning List<String> or even Collection<String>.
I have a lot of trouble getting behind your concept, which sounds a bit confused to me. At the very least, it sounds like horrible design. But I do have some suggestions:
You can make those utility methods static, then you won't need to instantiate your class at all to use them. This would be the simplest case.
You could pack your utility methods inside a static inner class of your frame, which essentially gets you around the requirement to only have one class per file.
Finally, do you just want the JFrame to disappear once the user is done with it, or do you want to terminate the application? dispose() will do only the former, your app will continue to run as a kind of headless zombie process.
Okay let's assume the methods you need aren't static.
In that case, remember the JFrame won't show up unless you call setVisible(true); So just make sure you never show the frame, and you can use whatever functions you want without it annoying the user.
Or you could design it properly and break out the utility methods into a separate class...

Categories

Resources