When adding new class extending JFrame (or java.awt.Frame) the class is added with main() method inside like this:
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new NewFrame5().setVisible(true);
}
});
}
Every JFrame class has its own main method and I guess all classes starts simultaneously.
How do I add frames without main methods?
Firstly, see The Use of Multiple JFrames, Good/Bad Practice?. Generally, recommended not to do it. See accepted answer for other possibilities (for example a JDialog)
As for your main concern, there's no way around netbeans creating the main method for top level containers like JFrame and JDialog. The logic seems right in the case of JFrame, as an application should only have one JFrame as the main top-level container for the application, but I'm not sure the logic behind the JDialog having a main method (as the dialog is usually run in the same JVM as the main JFrame). The only thing I can think is that the JDialog is created with a main for development purpopsed, if you want to test the dialog in stand-alone mode. But ultimately, you should delete the main method of the JDialog should you choose to use one.
Going back to the first point about multiple JFrames, other options I might recommend
Use a JDialog. Yes you will have to delete the main method, when going into production, as the dialog will be instantiated within the context of the main JVM and generally shouldn't run its own process.
Another option, depending on your requirements is to use a Cardlayout which will let you switch between views/panels (You can create JPanel forms in netbeans). See How to Use CardLayout in Netbeans GUI Builder for a working guide. And the official How to use CardLayout tutorial
An aside, if you are a beginner, I strongly suggest you put aside the builder tool and learn to hand code first. There may be many tutorials teaching you how to use the builder tool, but they may miss out on important concept in the swing architecture and swing in general. IMO this will greatly affect your understanding of how and why things work with the builder, causing a lot a headache when trying to debug. Keep Creating a GUI With JFC/Swing, the official tutorial handy and go through it.
Related
When making an application using Swing, I've seen people do one of the two things to create a JFrame. Which is a better approach and why?
I'm a beginner at Java and programming. My only source of learning is books, YouTube and Stack Overflow.
import {imports};
public class GuiApp1 {
public static void main(String[] args) {
new GuiApp1();
}
public GuiApp1() {
JFrame guiFrame = new JFrame();
guiFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
guiFrame.setTitle("Example GUI");
guiFrame.setSize(300,250);
................
}
AND
import {imports};
public class GuiApp1 extends JFrame {
public Execute() {
getContentPane().setBackground(Color.WHITE);
getContentPane().setLayout(null);
setSize(800, 600);
.............
}
public static void main(String[] args) {
Execute frame1 = new Execute();
frame1.setVisible(true);
}
}
Thoughts:
Avoid extending JFrame as it ties your GUI to being, well a JFrame. If instead you concentrate on creating JPanels instead, then you have the freedom to use these JPanels anywhere needed -- in a JFrame, or JDialog, or JApplet, or inside of another JPanel, or swapped with other JPanels via a CardLayout.
Avoid inheritance in general, especially of complex classes. This will prevent pernicious errors, such as inadvertent method overrides (try creating a JFrame or JPanel that has a getX() and getY() method to see what I mean!).
Avoid inheritance of complex classes if you are using an IDE: If you override a complex class, when you call methods on objects of these classes, you will have many, too many, choices of methods offered to you.
Encapsulation is good, is and allows for creation of safer code. Expose only that which needs to be exposed, and control that exposure as much as possible.
Prefer composition over inheritance.
The 2nd example uses inheritance, but for no good reason, since it does not change the functionality of JFrame.
As an aside, if those are examples of code you are seeing, find a new source1 supplementary. Even in the few code lines shown, each does highly questionable things. E.G.
Neither GUI is created on the Event Dispatch Thread.
getContentPane().setBackground(Color.WHITE);
getContentPane().setLayout(null);
setSize(800, 600);
The first part of the 1st line (getContentPane()) has not been necessary since Java 1.5
The second line uses a null layout, which will break in more ways I can count or describe.
The third line should best be replaced with pack();
JFrame guiFrame = new JFrame();
guiFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
guiFrame.setTitle("Example GUI");
guiFrame.setSize(300,250);
The first and 3rd lines could be contracted to: JFrame guiFrame = new JFrame("Example GUI");
The 2nd line is better set to guiFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
The 3rd line again sets a size to the frame.
Supplement
Having mentioned you do search SO, here is a tip. Check out the posts of the top 15 providers of answers in the Swing top users. Whatever advice/code you glean from these people, would commit few if any of the mistakes in those code samples. Some don't often (or ever) provide self contained examples like a few of us commonly do (and don't look to those examples necessarily for OO design as opposed to just technique), but whatever code they provide, or advice they give, should be highly considered.
Personally, the first approach (creating an instance of JFrame) is preferred, I prefer this because...
It doesn't lock your application into a dedicated container...you see a lot of people wanting to add applets to frames and frames to applets, if they had simple put the majority of there GUI in a JPanel to start with, they wouldn't have these issues.
It also means that the UI you create is much more flexible. For example, you can re-use it, either in the current application or future applications, you don't lock yourself in.
The main gripe I have with extending JFrame is, you're not actually adding any new features or functionality to it, which could be effectively re-used beyond using setVisible
The other issue I have with extending JFrame is people then promptly override paint, which is really, really bad. There are so many issues with doing this it's simply painful to have to repeatedly list them...
So...for more 2 cents worth. Create an instance of JFrame and add your content to it. If required, create a static method call showMyAwesomeGUI which does it for you...
The first approach is better.
Typically you are not adding any new functionality to the frame so creating a direct instance of the class makes sense.
Go for the first approach.
Because with that you can have more frames to be created. Because the application can have more than one window. As in the second case you can't create more frames.
It does not matter.
There are reasons why you might do one or the other, but absent any of those reasons it makes no difference whatsoever.
Now, if you were writing something that might operate from the command line or might be a GUI program, obviously you could want a 'main' class that was not a GUI class.
If you worked in a programming shop where one or the other was the standard, by all means follow the standard. There is no right answer to this one, and in fact very little to choose between them.
I'm fairly new to programming and definitely new to Java. I'm teaching myself before I begin courses this fall in computer science and I have a curiosity about syntax that I have seen from two different authors.
In one book, a JFrame is usually established by making the class an extension of JFrame
public class MyClass extends JFrame {
etc
However, another author, and also questions on this site usually establish a frame inside of the class as such:
public class MyClass {
JFrame frame = new JFrame();
Firstly, what are the advantages of one over the other?
It seems to me, and I'm hardly an expert, that making a class an extension of JFrame would make it easier to set parameters of the frame and also to add components to it.
IE in the extension format, you simply say
add(component);
However, in the other format, on must type:
frame.getContentPane().add(component);
which seems more tedious.
Can someone please explain succinctly the reason behind this or if it is simply a matter of preference. I have looked into this and have been unable to get a straight forward answer.
There are philosophical and practical reasons many (including I) prefer the latter:
Prefer composition over inheritance in general.
Only extend a class if you plan to alter its innate behavior (i.e., override one or more of its methods).
By not extending JFrame, it is easier to create classes that maximize cohesion and minimize coupling, and to write clean MVC-based code. A more important example of this concept is to avoid having your GUI code (your view code) implement any listener interfaces (your control code). It's OK for baby programs, but not for grown-up code that has the potential of getting complex.
By not extending a large and complex class such as JFrame, you reduce the risk of difficult to debug hidden override malbehaviors. Try extending JFrame or JPanel and giving the class a getX() and getY() method to see what I mean!
If you're using an IDE that gives suggestions of methods available to objects of your class, you greatly reduce the number (and complexity) of possible suggested methods if you don't override a huge complex class such as JFrame.
By gearing your Swing GUI's to create JPanels rather than override JFrame, you greatly increase the flexibility of how that GUI can be used. Now it can be placed in a JDialog, JOptionPane, a JApplet, inside of another JPanel as part of a more complex GUI or as part of a CardLayout view swap.... and I can go on and on.
On the same token as above, many of my GUI's do just that, create JPanels, that I can test in isolation by putting them in JFrames in small test programs before adding them to the greater whole of the application.
Traditionally you're not creating a special type of frame, so you shouldn't extend JFrame.
You're creating a JFrame and putting content in it, so the latter method is preferrable.
I.e. it's from an object oriented point of view it's cleaner to USE a JFrame, instead of extending one.
I'm working on a simple Java swing project. This is the code of the main class (name changed):
public class MainProg
{
private static MainProg program;
//mainWin is a JFrame
private MainWindow mainWin;
//Event handler class which extends MouseAdapter
private TrayManager trayMgr;
public static void main(String[] args)
{
program = new MainProg();
}
public MainProg()
{
mainWin = new MainWindow();
trayMgr = new TrayManager();
mainWin.startBtn.addMouseListener(trayMgr);
mainWin.setVisible(true);
}
}
As is clear, when the program starts, in main() it creates a new instance of the MainProg class, which then calls the constructor. In the constructor, it creates a new instance of the JFrame mainWin. It then attaches an event handler to a button on mainWin.
In the event handler class trayMgr, the only method is mouseClicked() which does nothing
except a System.out.println('Clicked');
The issue is, when I run this program in Netbeans, the JFrame is shown right away, but I seem to have to click the button 2-3 times before the message is printed in the console.
Is this just something specific to Netbeans, or do I have to change something to make the event handler be set before the window is made visible?
Your threading issue is not likely one that is causing your current problem, but there's the theoretic potential for problems, and I've seen some real problems associated with some of the more touchy look and feels. Quite simply you should queue your code that starts your GUI onto the Swing event thread. You do this by doing:
public void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(
public void run() {
program = new MainProg();
}
));
}
Someone else recommended using invokeAndWait(...) instead of invokeLater(...) but this can be risky especially if you inadvertently make this call from within the Swing event thread itself. For your situation you're better off using invokeLater(...).
But again, I think the main problem with the code you have shown was inappropriate use of MouseListener where an ActionListener should have been used. Learning to code any GUI library can be quite tricky, and for that reason, you can't assume anything. Check out the tutorials and learn from the experts. Also if you are considering coding Swing for the long haul, consider ditching the NetBean's code-generation utilities and learn first to code Swing by hand. You won't regret doing this.
Since you asked, the code I posted here is a Java SSCCE on a different topic. invokeLater is a way of running computations on the EDT. (There is also invokeAndWait, which would work fine here, but under some other conditions can cause a deadlock.)
In fact this example is perhaps a bit over-conservative. Some references say you can run Swing from the main thread the call to show() or setVisible(). However I have a program that misbehaves under Java 7 when I try that.
I'm looking for a specific functionality. I want to load a class that extends JPanel for instance and show that JPanel on a separate GUI class.
I'm looking for the ability to switch several of these classes out at will. I have an idea for an educational game software and the classes would be the different games.
I do realize that I can instantiate an instance of each class in my GUI class, but I ran into the issue of them not displaying properly when I try to switch between them. repaint() only works on the last class I added to my content pane. Not sure why as the multiple classes I instantiate are present, it just seems to ignore the preceding classes.
How to swap components?
You can either use CardLayout to switch all the component or add/remove them calling
container.revalidate();
container.repaint();
I did a GUI by my own which extends a JFrame. And I saw a program code from advanced programmer who imports the JFrame. I might know the difference between import and extend. But what advantage is given by which sort of implementation?
By "import" i presume you mean that your programmer friend's class uses a JFrame whereas your class is a JFrame. I don't think extending a JFrame is "wrong", but my preferred approach is to create and configure a JFrame rather than extending it. If there's really some protected method that you need access to then you might extend it but i'm sure that, in most cases, simply creating and configuring a standard JFrame is right - i have never found a need to extend it.
In other words, by inheriting JFrame with no real need to do that, you're just complicating your system. This is a same argument you would have when choosing inheritance versus aggregation with any other class. To find out what's right, you need to ask yourself if the class you're writing really is a JFrame which is a window widget. I suspect that in most cases you are writing a Swing application which needs a JFrame but which isn't one itself - it's a Swing application with some other purpose.