I was just curious where i should place the main function in a Java Swing program. It seems as If it's just way too short too create a brand new class for.
I would not recommend putting the main method inside of any of your Swing components. It doesn't fit well inside a Swing component because it has nothing to do with the components themselves.
Just create a main method in a separate class. It is alright that it is short.
Mushing the logic for running your program into the display logic seems like too much coupling.
I would not put it in the View class. If you're using MVC, and Swing is the View, then main belongs with Controller. That's the class responsible for starting the app, instantiating the View, and collaborating with Model objects to fulfill the use cases.
The Controller should implement the Listener interfaces, because it responds to Swing events as they occur.
I would not have your View extend JFrame. Make the working bits of Swing extend JPanel. When the Controller instantiates the View, it should create a JFrame, add in the JPanels it needs, register itself as the Listener for all Swing events, and make the JFrame visible. At that point your app is up, running, and ready to go.
Put it into your main JFrame class
public class MyFrame extends JFrame {
public static void main(String args[]) {
new MyFrame();
}
MyFrame() {
// ...
}
}
You can put it in any class. It makes sense to put it in the class that represents your main dialog in your app. There is no need to create a class just for main.
Related
I've recently started learning how to use Swing and graphics in Java and have come across two different approaches for designing a GUI.
1) To have the program's main method in an instatiation of the JFrame class.
2) To have a class which calls SwingUtilities.invokeLater() at the end of the main method to delay the thread that deals with graphics until after the initialisation of the main method.
e.g. 1.
class program extends JFrame {
public static void main(String[] args) {....}
}
e.g. 2.
class program implements Runnable {
public static void main() {
program p = new program();
SwingUtilities.invokeLater(p);
}
public void run() { ... }
}
How important is it to make the program thread safe as in approach 2? Also, what are the advantages and disadvantages of each approach? i.e. When would you use one approach over the other? etc.
I have run into simple Swing applications that fail outright if not started on the Swing event thread, this happened first for me when setting look and feel. Also correct running is not guaranteed in any situation unless the GUI is started on the Swing event thread, and so for general Swing advice, I recommend
Always try to start your GUI on the Swing event thread.
Avoid extending JFrame as it's almost never needed, and limits your code.
Do extend JPanel if your GUI does graphics, especially if it does animation
Or if you want to have more control over setting the size of your GUI, and override getPreferredSize() for this.
You can paint yourself in a corner by having your class extend JFrame, forcing you to create and display JFrames, when often more flexibility is called for. More commonly your GUI classes will be geared towards creating JPanels, which can then be placed into JFrames or JDialogs, or JTabbedPanes, or swapped via CardLayouts, wherever needed. This will greatly increase the flexibility of your GUI coding. You also never will want to draw directly in a JFrame as this risks mis-drawing one of its critical components but do often draw in JPanels, especially if doing animation, and for this you will need to extend JPanel.
I have a class that creates a JFrame. When the JFrame is created it has a start button. When the start button is clicked, it runs two threads until the stop button is clicked. The two threads are in another class file. From the class that contains the threads, how can I access the JFrame instance in order to change value that are displayed?
In order to acheive this you have to pass the reference of JFrame using this keyword.
To have access to a private instance within another class, I think you should use agetter.
Example:
//JFrame declaration
private JFrame frame;
//Getter
public JFrame getFrame() {
return frame;
}
As noted by one answer, you can pass in a reference of the GUI or view into any class that needs it, for instance by passing the GUI class into the other class's constructor parameter, and using the parameter to set a field, but having said that, there are caveats:
Always be sure to make Swing state changes on the Swing event thread (the EDT). Since you're using background threading, this means that you will either
use a SwingWorker as your background thread, and notify the GUI of changes via the publish/process method pair, or
your SwingWorker can notify observers of change via PropertyChangeListeners and "bound" properties, or
if using a standard Thread/Runnable, you will need to be sure to queue Swing calls onto the EDT using SwingUtilities.invokeLater(someRunnable)
Even better is to use a Model-View-Control type structure, but even if you do this, the model should be changed on the EDT for the same reasons above.
As a side recommendation in general I try to avoid making classes that extend JFrame as that unnecessarily restricts my code to creating just JFrames.
Note that this help is very general, but if you need more specific help, then you will want to post more specific information regarding your problem and your pertinent code.
I am making a game which will have three games implemented in it. I started off my code in a single class, now that I want to move it around into a MVC format I am having errors. I started off with writing all the code in GameView Class, I now want to move some of the code from this class to a SView Class. The problem is that I have intialised the JFrame in GameView class and it cannot find the variable frame when I move my code to SView class. So then I have been told to make it into a panel and then move it but it's just messing up my game.
You have to organize things a little differently. Some things to consider:
Is GameView your main window? Make it so GameView extends JFrame.
Is SView a panel? Make it so SView extends Panel.
Another thing to think about: SView is some panel that you want to add to your GameView, but it's not the responsibility of SView to add itself. Instead, simply instantiate and assemble these components somewhere outside both of these classes, f.e.:
GameView gameView = new GameView();
gameView.add(new SView());
You could also have GameView add a new SView() in its constructor code instead.
Anyway, the main point here is that a component should not concern itself with adding itself to its parent, just with creating its own content/children.
Good luck.
Some suggestions:
The main GUI would use a CardLayout so you can swap JPanels easily.
The main function of the select game menu will be to swap JPanels, so the game selected is visualized and then initialize the selected game.
Work on each game individually. Gear each individual game class towards produding a JPanel to hold the game. Give each game class a main method for testing that would create a JFrame, create a game class instance, place the instance's JPanel into the JFrame, initialize the game and display it.
Once the game is working on its own, try adding it to your larger GUI, the one that can show multiple games.
Consider having each game class implement a common interface for common functionality. For example you could give the interface an initialize() method that each game class would override.
Each game class would need to be MVC-based so that it has a model, a control class(es) to interact with the model and a view class that displays the state of the model on the JPanel as noted above.
So I have two classes.
One is a class called Main. The Main class is supposed to process some data.
Then I have another class called MainApplet, an Applet of course.
How can I display MainApplet from the Main class? This is what I have so far, but the applet does not show:
public class Main {
public static void main(String args[]) {
System.out.println("Starting application.");
MainApplet Main = new MainApplet();
Main.setVisible(true);
Main.show();
} }
How can I display MainApplet from the Main class?
You don't. You display an applet from HTML code.
Are you sure your GUI is in fact an applet? Does it extend JApplet or Applet? If so and you want to show it on the desktop through code, then don't make it an applet but instead display a JFrame. The Java Swing tutorials will show you how to do this: How to use Swing Components
Edit
you state:
Basically I have a Main class that is not an applet. It doesn't extend anything. Then I have another class named MainApplet that is an applet (extends JApplet). I want to run Main first, then display MainApplet after... but I can do it the other way around if needed.
You don't sound like you're running your code from a web page (for some reason you're still keeping this information from us), so the solution is not to use applets for this. Instead create a JFrame. Please check out the tutorials that I've linked to above since an applet is not appropriate for your needs.
You will have a main that creates your GUI, that passes any information into the GUI via constructor or method parameters, and then that tells the GUI to show itself (by calling setVisible(true) if it's a JFrame).
Your mainApplet class must extend Applet. You would then replace your main(...) method with init(...) as this is the method that gets called when you open an Applet. You can test this in most environments such as Eclipse. It order to actually put the Applet on a webpage, you must tell the applet to display using HTML in the page.
In the GUI book we use in class there are many examples of how graphical user interfaces are made in Java. So many examples, that I'm very confused regarding which one should be used when it comes down to a big application.
So I've seen examples
in which the main class extends JFrame
where the JFrame object is created inside the main method
where the main class extends JFrame AND implements ActionEvent interface
where Listener classes are declared inside the main class
Sure, I can work with all of these, but right now, as I don't have any kind of experience, I don't see the benefit of using any of them. Is actually one of them the correct way to do it or it depends on my sittuation?
Thank you!
"Is A" or "Has A"? This is the question that should be asked when considering extending a class. If the new class "Is A" frame, extend frame, but if the class just needs a reference to a frame, don't extend.
In fact, if a custom component is required, extend a JComponent or JPanel, then add that to a frame, ..applet, window, JInternalFrame, dialog, constraint of a layout, part of a split pane..
Listeners
As to the listeners. Rather than traverse a huge if/else structure in the single actionPerformed() method to determine the required action, it is more optimal to either:
Create a listener for each control that needs it.
Create an instance of an AbstractAction that might be used for multiple controls ('copy' button, menu item etc.).
Summary
So (generally) for the:
JFrame, don't extend.
Listeners, create and add as needed.
Honestly, it depends on the situation. One basic rule when coding is to "code to abstract classes or interfaces".
So, in a nutshell, have a class extending (or implementing) a JFrame (or whatever interface or class) and/or have one doing the same thing with ActionListener.
It is all about the maintainability, flexibility and cleanness of your code.
Standard approach: use EventQueue in method main, that creates main form. In that case all your operations will be asynchronous
in which the main class extends JFrame
the main calss doesn't have to extend JFrame. if it doesn't you should create a JFrame object like you do with any other class
where the JFrame object is created inside the main method
If the MainClass extend JFrame it created inside the c'tor (in the super() ).