Java using MainWindow functions - java

So I have a MainWindow.java that creates the window with all the controls and things. I put a menubar object on the window, one of the options in the menubar is make the program a server. So here's the main window looks like this:
public class MainWindow extends javax.swing.JFrame {
//all code including menubar click action handler
//Server.start()
}
When you click the option, it goes into the Server.java class and starts the server. Here's the skeleton of that class:
public class Server {
public static void start(String port) {
try {
startServer(Integer.parseInt(port));
} catch (Exception e) {
e.printStackTrace();
}
}
public static void startServer(int PORT) throws Exception {
...
}
private static class ClientListenThread extends Thread {
public ClientListenThread(Socket socket, int ClientNumber){
...
}
public void run() {
...
}
}
private static class ServerSendThread extends Thread {
public ServerSendThread(Socket socket) {
...
}
public void run() {
...
}
}
}
The problem now is that once it gets inside the Server class, it listens for connections and connects fine but I just can't go back to the MainWindow class. It stays within the Server class. I can't even call the MainWindow functions by doing MainWindow.function() because it says
Cannot make a static reference to the non-static method function() from the type MainWindow
I even tried putting all of the Server class code into the MainWindow class or just above it but Java didn't like that and said it wanted it in a separate file.
How exactly do I reference MainWindow functions from within the Server class? Or is there a better way of going about this?

You need to either create an instance of the MainWindow class using for instance MainWindow m = new MainWindow() and then calling the function as m.function(), or declare your function as static.
Static means that you can call a function without creating an instance of the object. This is why you get the error, since your function is not static, so it requires an instance of the object to be called.
You'll also want to make sure that the MainWindow class is imported into the Server class.

Related

Using a JTextArea in a different class

I have a class for my GUI which I created using Swing UI Designer.
All the components were automatically made private but now I need output some text in a variable called consoleTextArea from outside of the UI.class
When I set consoleTextArea to public static I get an error saying "UI.form: Cannot bind: field is static: indeed.UI.consoleTextArea"
...
public static JTextArea consoleTextArea;
...
...
UI.consoleTextArea.setText("abc");
...
\src\indeed\UI.form: Cannot bind: field is static: indeed.UI.consoleTextArea
You can change the value of your label/textArea, through an instance of your UI class.
public class UI {
// ...
private TextArea consoleTextArea = new TextArea();
//
public void setTextInTextArea(String text) {
this.consoleTextArea.setText(text);
}
}
Having setters like this, you can manipulate your textArea from within a different class. This other class, however, must have access to the instance of UI, either instantiate it itself, or getting it passed as a parameter
public class OtherClass {
UI ui = new UI();
public void doSomething() {
ui.setTextInTextArea("New text");
}
}
or something like:
public class OtherClass {
public void doSomething(UI ui) {
ui.setTextInTextArea("New Text");
}
}
Instead of making the field public (not static public) you should rather add a method like this to your class:
public void setConsoleTextArea(String value) { consoleTextArea.setText(value); }
Then you can do
UI.setConsoleTextArea("abc");
without having to mess with the consoleTextArea field that is automatically generated.

Is there a way to use methods between classes?

I have two .java files in the same package. I am planning on making the first .java file the underlying code and the second .java file the GUI swing interface.
My problem I encountered was when working on the GUI part of the project, I needed to access several methods from the .java file with the code. My .java file with the code is a like this:
package same;
public class HFSim extends ApplicationTemplate
{
private static class AppFrame extends ApplicationTemplate.AppFrame
{
public myMethodIWanttoUse()
{
//code
}
And in my GUI .java:
package same;
public class GUI extends JFrame
{
public GUI()
{
public void actionPerformed(ActionEvent e)
{
//this is where I want to use the method from above
Is there a way to get that method to be used in the GUI portion? Or is there a better way to approach this problem? thanks in advance.
You have multiple solutions to your problem. The first question you should answer is how these methods you need to call qualify themselves.
Are they utility methods? (They don't require an instance of an object to work on)
Are they attached to a single instance of an object?
Do you need to call methods of a specific object more than just methods?
You can either:
Declare them static and call them, eg HFSim.AppFrame.myMethoIWanttoUse();
Declare a static instance of the object containing them, eg
public class HFSim extends ApplicationTemplate {
public static final AppFrame appFrame = new AppFrame();
...
}
public class GUI extends JFrame {
public GUI() {
public void actionPerformed(ActionEvent e) {
HFSim.appFrame.myMethodIWanttoUse();
}
}
}
Pass the instance of the object to the other one:
public class GUI extends JFrame {
private final HFSim.AppFrame appFrame;
public GUI(HFSim.AppFrame appFrame) { this.appFrame = appFrame; }
public void actionPerformed(ActionEvent e) {
appFrame.myMethodIWanttoUse();
}
}
Make methodIWantToUse() static by replacing
public myMethodIWanttoUse()
with
public static myMethodIWanttoUse()
Secondly, make AppFrame marked as public instead of private.
Then just call you method like this HFSim.AppFrame.myMethodIWantToUse().
Edit:
Alternatively, you don't have to make your method static. Just add this in your GUI code:
HFSim.AppFrame frame = new HFSim.AppFrame();
frame.myMethodIWantToUse();
Still, no matter what, you have to make AppFrame be public.

java composition

I'm trying to use and learn the composition's relation between classes respecting the flexibility of OOP programming, a small sample code that explains what I'm trying to do:
Main class:
public class MainFrame extends JFrame {
private Test test;
public static void main(String[] args) {
new MainFrame();
}
public MainFrame() {
initFrame();
}
private void initFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(100,100);
setResizable(false);
setUndecorated(true);
setVisible(true);
setLocationRelativeTo(null);
test.update();
}
public void setNumber(int i) {
System.out.println(i);
}
}
and this class:
public class Test {
MainFrame mainFrame;
public void update(){
mainFrame.setNumber(10);
}
}
if i run this i will get :
Exception in thread "main" java.lang.NullPointerException
how can I change the code so that:
The Test class refers only to the MainFrame instance created in the main, not to create a new instance of the MainFrame inside the Test class
It is possible to avoid the use of static classes and static functions to do this?
The Test class refers only to the MainFrame instance created in the
main, not to create a new instance of the MainFrame inside the Test
class
Sorry, this makes no sense. That's not how Java works, and the runtime is educating you.
This code is wrong from top to bottom.
The instance in the Test class is null because you never initialized it.
The Test class knows nothing about the main method in the MainFrame class, nor should it.
The instance in that main method goes out of scope as soon as the method exits and is garbage collected.
Why would the MainFrame class have a reference to a Test instance inside it? Bad design. It's called a circular dependency. Once you add it, you can never separate the two classes. Sometimes they can't be helped, but I see no reason for it at all here, especially for a class named Test. Test can know about MainFrame, but MainFrame need never know about Test. You've done it wrong.
You don't need to extend JFrame. You aren't adding anything by extending. I'll bet this should be a JPanel that you'll add to a JFrame.
In stead of advising about design, I'll just put a way to achieve it.
public class MainFrame extends JFrame {
private Test test;
public void setTest(Test test) {
this.test = test;
}
}
and
public class Test {
MainFrame mainFrame;
public Test(MainFrame mainFrame) {
this.mainFrame = mainFrame;
this.mainFrame.setTest(this);
}
}
Good luck.
Quick fix for your NullPointerExceptions:
public class Test {
MainFrame mainFrame;
public void update(){
mainFrame.setNumber(10);
}
public void setMainFrame(MainFrame mainFrame) {
this.mainFrame = maninFrame;
}
In initFrame():
test = new Test();
test.setMainFrame(this);
test.update();
Otherwise I agree, the concept you're trying has a lot of misunderstanding. Try to separate the Test and MainFrame logic.

Given two classes, creating an object of each class in one another results in StackOverflow Exception

Given two classes, creating an object of each class in one another results in StackOverflow Exception. It is a JAVA project btw.
There are multiple classes in my projects and for using the other classes, I thought i would create objects of the other class and use it.
Say i have class Main and class GUI. I have created object of GUI in MAIN and initialized it. Similarly i have created an object of MAIN in GUI and initialized it.
Now this gives me a Stack Overflow Exception as the the constructor calls are going deep into recursion.
How do i go about it?
One possible solution i can think of is making variables and methods of one class STATIC.
Any other solution? Please suggest.
You should be passing an instance of one of you classes into the constructor of the other class.
public class Main {
private final GUI gui;
Main() {
gui = new GUI(this);
}
}
public class GUI {
private final Main main;
public GUI(Main main) {
this.main = main;
}
}
You could also use setters instead of constructors. I don't like this option as much, because you lose the ability to make your variables final.
public class Main {
private GUI gui;
Main() {
}
public void setGui(GUI gui) {
this.gui = gui;
}
}
public class GUI {
private Main main;
public GUI() {
}
public void setMain(Main main) {
this.main = main;
}
}
public static void main(String[] args) {
Main main = new Main();
GUI gui = new GUI();
main.setGui(gui);
gui.setMain(main);
}
Singleton ? (if it works for your app )

Is a static-utility method not the best approach in this scenario?

I have this class, let's say Foo. This class is responsible for creating/showing a JFrame, which requires heavy customization.
public class Foo{
private static JFrame frame;
public static void createAndShowFrame(){
//do stuff
}
public static JFrame getFrame(){
return frame;
}
}
And I have this other class, let's say Launcher, that serves as the entry-point of the application. This class is responsible for initiating the construction of the GUI
public class Launcher{
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
Foo.createAndShowFrame();
}
});
}
}
The design problem is getFrame(). This method was required because other dialogs require this as their parent frame. Unfortunately, this exposes the frame and seems to void the static-utility method.
I guess my question is, is there a more sound design approach to this? Am I making any sense? I basically wanted to create and show a frame without having to extend it.
See my Rule of Thumb question.
Independently of the question of exposing the JFrame or encapsulating it, why does this class (the methods/fields) have to be static? The object oriented way would be to have them ordinary (instance) methods:
public class FrameCreator {
private JFrame frame;
public void createAndShowFrame(){
//do stuff
}
public JFrame getFrame(){
return frame;
}
}
Then in your launcher class, you would create an object of this class and call it's methods:
public class Launcher{
public static void main(String[] args){
final FrameCreator f = new FrameCreator();
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
f.createAndShowFrame();
}
});
}
}
If you need to access the created frame from somewhere else, pass this code the FrameCreator instance that created the frame.
I don't see the advantage of the use of invokeLater() (EDIT - in this case (since you call it from main() ) . If you have a heavy GUI processing to do, just do it on main thread (because you have to anyway). If most of the work can be done in background, do it in background and publish the results on the main thread. (using invokeLater()). [This part is only my opinion, not based on some docs etc...]
Finally, if you don't want to expose the frame, create a method setChildComponent(JComponent component) that will receive a JComponent and set the frame as its parent internally. This way you would avoid exposing the private JFrame.

Categories