When writing a standalone java application, I see a lot of beginners code in the static context.
I used to get around this problem by creating an instance of the class in main, and working from the constructor.
I've added a few examples of a very simple standalone program, and would like to know if there are best practises for "leaving" the static context.
I would also like to know if there are things a standalone java program should be doing in the static context or specifically in the main method, what it's function is besides being the entry point of every standalone java program.
Any reading material is also welcome!
import javax.swing.JFrame;
import javax.swing.JLabel;
public class ExampleStatic
{
JLabel label;
public static void main(String[] args)
{
//Option 1 - Work from static context:
JFrame frame = new JFrame();
frame.setBounds(10,10,100,100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel staticlabel = new JLabel("static");
frame.add(staticlabel);
frame.setVisible(true);
//Option 2 - Create instance, call initialisation function
ExampleStatic e = new ExampleStatic();
e.initialise();
//Option 3 - Create instance, handle initialisation in constructor
new ExampleStatic(true);
}
public ExampleStatic(){}
public ExampleStatic(boolean init)
{
JFrame frame = new JFrame();
frame.setBounds(10,10,100,100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
label = new JLabel("constructor");
frame.add(label);
frame.setVisible(true);
}
public void initialise()
{
JFrame frame = new JFrame();
frame.setBounds(10,10,100,100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
label = new JLabel("init function");
frame.add(label);
frame.setVisible(true);
}
}
Option 2 and Option 3 both are fine, as both provide the loose coupling as well if you want to use your instance somewhere else in other classes you can use it easily. But if everything you will write in Main method you are going to loose the scope and its reusability.
The JVM needs main to be static, after that you're free to do what you want. I would call a non-static "second main" that would handle initialization and then any further processing in different methods (or classes).
I would avoid putting things in the constructor, unless you really feel it's the right place for them.
Related
I have created a form with IntelliJ's GUI builder, it has a working main() method, the form works properly and has some listeners attached.
In addition to that I have a custom class where I want to call that GUI I created with IntelliJ's GUI builder. I can accomplish this by copying the code within the "main" method in the GUI's class and placing it in my custom class and if I run my custom class the form is indeed displayed.
But thats about all I can do with the created GUI, I can only call it. I can't do other things like dispose that GUI form instance (frame.dispose()) and open another form because I don't know how to get access to the frame instance from my custom class.
Can someone please assist me with this? I thought it would save me a lot of time if I used the GUI builder as opposed to writing the GUI code from scratch for several forms.
I solved the problem by creating a method in the GUI form class called load() which contains the JFrame setup
GUI Form Class
public void load()
{
JFrame frame = new JFrame( "Login Form" );
frame.setContentPane( new LoginForm().mainPanel );
frame.setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
and then in my main class I called it with new LoginForm().load();.
In order to dispose of the initial GUI form and open another one I created a helper method inside the GUI form class called getMainFrame()
private JFrame getMainFrame()
{
return (JFrame) SwingUtilities.getWindowAncestor( this.mainPanel );
}
after that inside the GUI form class constructor there is logic to dispose of the frame when a condition is met
if (age.equals("42"))
{
//load the appropriate form
new MainForm().load();
//dispose of this current form
this.getMainFrame().dispose();
}
First, give a name to your root panel:
Then create a getter for it, and you can use it in a JFrame by
JFrame f = new JFrame();
f.add(new YourGuiClass().getMainPanel());
f.setVisible(true);
When you want to dispose it, dispose the JFrame instance should work.
Edit
You said you want to dispose the JFrame in your GUI form class logic, try this:
class YourGuiClass {
private JFrame f = new JFrame();
private JPanel mainPanel;
public void load() {
f.add(mainPanel);
f.setVisible(true);
}
public void dispose() {
f.dispose();
}
}
By this you can operate the GUI form class without knowing anything related to Swing in the main function:
public static void main(String... args) {
YourGuiClass myGuiClass = new YourGuiClass();
myGuiClass.load(); // it now shows itself
if (someLogic()) myGuiClass.dispose(); // you can
// also call this elsewhere as you like
}
How can I embed a PApplet into a JApplet ?
I wanted to add it to a JPanel inside the applet, but I couldn't.
If any of you know how I can do this. ??
As of Processing 3, you can no longer do this. PApplet no longer extends Applet, so it can't be treated as a component.
For 95% of users, this is okay. Applets are dead anyway, so you really shouldn't be using them. If at all possible, you should try deploying with Processing.js.
If you need to execute a Processing sketch from Java code, then you should use the PApplet.main("YourSketchNameHere"); function to launch it. Processing will take care of the window for you.
If you really need to treat a PApplet as a component, then you're going to have to go through its PSurface. The PSurface class contains a getNative() function that returns an object that can be treated as a component. But that's overkill for most Processing users.
Prior to Processing 3, this code should have worked for you as #Kevin has explained. So, if your question is directed towards understanding a legacy code here is what you will need to know:
import javax.swing.JFrame;
import javax.swing.JPanel;
class MyPApplet extends PApplet implements ActionListener{
#Override
public void setup() {
super.setup();
// setup
}
#Override
public void draw() {
// my draw code
}
}
public class PAppletDemo {
public static void main(String[] args) {
final JFrame frame = new JFrame("PApplet in Java Application");
JPanel panel = new JPanel();
//create an instance of your processing applet
final MyPApplet applet = new MyPApplet();
applet.init();
panel.add(applet); // From processing 3, this will give you error that applet is not a Component
frame.add(panel);
frame.setSize(applet.getSize().width, applet.getSize().height +200);
frame.setVisible(true);
}
}
To circumvent this, you will need to use PSurface getNative() function. Please refer to the example and discussion given on this link.
I want to include one java file into another. Both have the main functions in it. One file looks similar to the following:
public class FileShow
{
public static void main(String args[])
{
JFrame guiFrame = new JFrame();
JFrame.setDefaultLookAndFeelDecorated(true);
JDialog.setDefaultLookAndFeelDecorated(true);
//make sure the program exits when the frame closes
guiFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
guiFrame.setTitle("RTL Parser GUI");
guiFrame.setSize(500,500);
//This will center the JFrame in the middle of the screen
guiFrame.setLocationRelativeTo(null);
JPanel comboPanel = new JPanel();
JTextField handle = new JTextField(30);
comboPanel.add(handle);
guiFrame.add(comboPanel);
guiFrame.setVisible(true);
}
}
whereas my other java file is:
public class AnotherFile{
public static void main(String[] args) {
new AnotherFile();
}
public AnotherFile()
{
guiFrame = new JFrame();
//make sure the program exits when the frame closes
guiFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
guiFrame.setTitle("Assertion-Based GUI");
guiFrame.setSize(500,500);
//This will center the JFrame in the middle of the screen
guiFrame.setLocationRelativeTo(null);
JPanel comboPanel = new JPanel();
JTextField handle = new JTextField(30);
comboPanel.add(handle);
guiFrame.add(comboPanel);
guiFrame.setVisible(true);
}
}
Is there any way to combine both the files and run together, since both have the main functions in it?
How do i combine both the files in same java file and run both of them together?
You just can't do that. Each Java file should have only one main method.
But you can better organize your files to do what you want:
public class FileShow{
public void doSomething(){
//...
}
}
public class AnotherFile{
public void doSomething(){
//...
}
}
public class mainClass(){
public static void main(String args[])
new FileShow().doFileShow();
new AnotherFile().doAnotherFile();
}
}
I would just add 'AnotherFile' object in the main method of Fileshow. You can only have one main method.
So in Fileshow.java, in the main method add
Anotherfile a = new Anotherfile()
From what you wrote, it is completely unclear, what you want to achieve. Include two Java classes into one .java file? Into one .jar file?
What do you mean by "run together"?
Combining two top-level Java classes in one source file is possible (according to JLS), while only one of them may be public. I believe though, it is not a best practice, just because you get quite a messy lifecycle of your classes. But if you still want to do it, you must make one of them either package private or nested.
Getting both to one jar is trivial. Just call jar cf jarname <classes>. It would also be possible to call the main methods separately by explicit mentioning them in java command line, like java -cp jarname <package>.FileShow.
Still, I'm not sure I understood your question right.
In Java, each Java file can contain one public class and by default JDK will call it's main method. If you have two classes both having a main method and you want to keep it in one Java file, the two classes can not be public, one must be an inner/nested class. I have given an example below.
public class FileShow
{
public static void main(String args[])
{
AnotherFile.main(args);;
// Your code
}
static class AnotherFile
{ // as it contains a static method
public static void main(String[] args) //or any static class
{
new AnotherFile();
}
public AnotherFile(){
// Your code
}
}
}
Logically it will work. But I highly discourage to go with this. It is not standard.
SEE UPDATE AT THE BOTTOM!!
I've tried to figured out how to do this for a couple of days but so far I have had no luck.
Basically what I want to do is have a combobox, which when an option is selected loads an applet, and passes a value to the applet.
Here is the code for the ComboBox class, which is supposed to open the other class in a new window. The other class is the main class for an applet. They are both in the same project but in different packages. I know that there aren't any errors with the rest of the code.
//where I evaluate the selection and then open SteadyStateFusionDemo
// more selections just showing one code block
combo.addItemListener(new ItemListener(){
public void itemStateChanged(ItemEvent ie){
String str = (String)combo.getSelectedItem();
if (str.equals("NSTX")) {
machine = "A";
JFrame frame = new JFrame ("MyPanel2");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
SteadyStateFusionDemo d = new SteadyStateFusionDemo();
frame.getContentPane().add (new SteadyStateFusionDemo());
d.init();
frame.pack();
frame.setVisible (true);
And just to cover everything here is the beginning of the init() method of SteadyStateFusionDemo as well as the main method in the class. Too much code to post otherwise. There are several different privates before the init method.
//method that initializes Applet or SteadyStateFusionDemo class
public void init() {
//main method of the SteadyStateFusionDemo class
public static void main (String[] args) {
JFrame frame = new JFrame ("MyPanel");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add (new SteadyStateFusionDemo());
frame.pack();
frame.setVisible (true);
What am I doing wrong? Why doesn't my class load?
UPDATED: Changed the code so that a JFrame opens and then the JApplet loads inside. I have successfully done this in a test Java applet but for some odd reason it won't work with this Applet. I even set up the test in a similar way (The code for this is virtually the same, except with different class names, and of course a much, much shorter init() method). Can someone help me figure out why this isn't working? Also, a JFrame will open if I delete the lines referring to SteadyStateFusionDemo, but once I reference it won't work. Why does this happen?
UPDATE:
Based on your feedback, it seems you are trying to achieve the following:
Use the code of an existing Applet (found here) in a Desktop application (i.e. in a JFrame).
Converting an Applet to a Desktop application is an "undertakable" task, the complexity of which depends on how much "Applet-specific" stuff is used by the Applet. It can be as simple as creating a JFrame and adding myFrame.setContentPane(new myApplet().getContentPane()); or as complex as...hell.
This tutorial might be a good place to start.
After taking a look at the Applet at hand, it seems to be fairly easy to convert it. The only complicating factor is the use Applet's methods getCodeBase() and getImage(URL) (somewhere in the code). These two methods result in a NullPointerException if the Applet is not deployed as...an Applet.
So, what you can do is override those two methods in order to return the intended values (without the exception). The code could look like this:
/* Import the necessary Applet entry-point */
import ssfd.SteadyStateFusionDemo;
/* Subclass SSFD to override "problematic" methods */
SteadyStateFusionDemo ssfd = new SteadyStateFusionDemo() {
#Override
public URL getCodeBase() {
/* We don't care about the code-base any more */
return null;
}
#Override
public Image getImage(URL codeBase, String imgPath) {
/* Load and return the specified image */
return Toolkit.getDefaultToolkit().getImage(
this.getClass().getResource("/" + imgPath));
}
};
ssfd.init();
/* Create a JFrame and set the Applet as its ContentPane */
JFrame frame = new JFrame();
frame.setContentPane(ssfd);
/* Configure and show the JFrame */
...
The complete code for an example JFrame Class can be found here.
Of course, you need to have all Classes from the original Applet accessible to your new Class (e.g. put the original Applet in your classpath).
I have a piece of code here and I'm not sure what a couple of commands do:
//this bit is the body of the main method
//lots of stuff omitted
project frame = new project();
frame.createGUI();
private void createGUI() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
panel = new JPanel();
}
So when frame.createGUI(); is called, what happens with the two commands in createGUI();?
Are they
setDefaultCloseOperation(EXIT_ON_CLOSE);
panel = new JPanel();
or
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.panel = new JPanel();
or is it something else entirely?
I'm quite new at Java, started year 12 Computer Science this year, but am a bit ahead of class.
Thanks for your time!
Every non static method in Java has an hidden parameter called this. It's value is the object in front of the dot in the invocation. Inside the body of methods, invocations of other methods implicitly have this. in front of them. So does the use of variables, if they cannot be resolved locally. If the this reference was explicit, your method would look like this:
private void createGUI(project this) {
this.setDefaultCloseOperation(this, EXIT_ON_CLOSE);
this.panel = new JPanel();
}
In the invocation of createGUI in your main method, what is really happening is something like this:
frame.createGUI(frame);
When running createGUI the this reference is a reference to frame.
setDefaultCloseOperation(EXIT_ON_CLOSE);
Sets the operation that happens when the user closed the Window (JFrame). The method is for JFrame. If the class extends JFrame then setDefaultCloseOperation(EXIT_ON_CLOSE); is fine since it will call the method of JFrame if not then it should be frame.setDefaultCloseOperation(EXIT_ON_CLOSE); but this will work if project extends JFrame
panel = new JPanel();
This creates a new panel.
frame.createGUI(); means that your object frame which u defined a line above calls the method createGUI()
setDefaultCloseOperation(EXIT_ON_CLOSE); this means that when the user click X button in the left top corner of the window will close the that window.
you can experiment a bit and delete setDefaultCloseOperation(EXIT_ON_CLOSE); from the createGUI() method and see what happens
if u want to learn more, look here
Your two alternatives are really one and the same. In both cases, you are calling methods of the frame object you created. From within a method of the class, you don't have to specifically say: this.doSomethimg() or this.myField = 123, you can just write doSomething() or myField = 123. From methods outside the class, you have to indicate for which instance you want the method called.