i just started learning swings. And thought of trying out a simple program, but i can't run it.
import java.awt.*;
import javax.swing.*;
class MyDrawPanel extends JPanel
{
public void paintComponent(Graphics g)
{
g.setColor(Color.orange);
g.fillRect(20,50,100,100);
}
}
I am getting the following error:
Exception in thread "main" java.lang.NoSuchMethodError: main
My Question: Do we need to have a main method in every class we want to run? Can't JVM run any class which doesnt have a main method. Here i don't require a main class i think, cuz this paintComponent method should be called by the system, right?
P.S: I am using plain vanilla cmd to compile and run.
java is rather simple, when you give it a class file it will load it and try execute a program. Java programs are defined to start in the "public static void main(String... args)" method. So a class file missing this function has no valid entry point for a program.
To make java call your paintComponent() method you have to add an instance of your class to a toplevel container like JFrame or for web applications an JApplet. (Applets don't use a main method as they are executed as part of a web page and not a standalone app.)
Example:
import javax.swing.*
public class MyDrawPanel{
public static void main(String... args)
{
JFrame frame = new JFrame(200,200);//A window with 200x200 pixel
MyDrawPanel mdp = new MyDrawPanel();//Panel instance
frame.add(mdp);//Add the panel to the window
frame.setVisible(true);//Display all
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//exit when the window is closed
}
}
As vodkhang said, you need a "main" method. Make sure it looks just like this:
public static void main(String[] args)
{
// your code here.
// this example will use your panel:
// create a new MyDrawPanel
MyDrawPanel panel = new MyDrawPanel();
// create a frame to put it in
JFrame f = new JFrame("Test Frame");
f.getContentPane().add(panel);
// make sure closing the frame ends this application
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// show the frame
f.setSize(100,100);
f.setVisible(true);
}
Yes, every Java program that you want to run needs a main method with exactly this signature:
public static void main(String[] args)
You can run java code from within other systems (like web servers and etc without a "main") but to simply run it, the main is the entry point. Put it where-ever you want to start a program running.
When running, make sure you get the class name right to help it find your main method. In your case, if you are running java by hand in the same directory as your MyDrawPanel.class file you would do this:
java -cp . MyDrawPanel
If you are running from inside a developer tool, then it will provide a way to run the class you are looking at.
Do we need to have a main method in
every class we want to run?
You need a class with a main method to start a JVM.
Can't JVM run any class which doesnt have a main method.
Not initially.
Here i don't require a main class i think, cuz this paintComponent method should be called by the system, right?
Wrong. It's true that the paintComponent() method will eventually be called by "the system", specifically the Swing Event Dispatch Thread. But that needs to be started first, which happens implicitly when you create a window and make it visible. And that in turn can only happen in a main method.
You need a main method in the class that you want to run the program for. It is mandatory. How can the JVM know which method they should call to start if you have multiple methods. They can guess but most of the time, the guess may go wrong. So, provide a simple main method will help
Related
So I'm very new to the JSwing world, having not covered much in my AP Computer Science class I finished last year. So, I am familiar with inheritance and all the core parts of the Java language, but I can't see the difference between the two methods main() and run().
My code here works just fine for right now:
Main Class:
import java.awt.BorderLayout;
import java.awt.Component;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Main {
private JFrame frame;
public Main() {
frame = new JFrame("SoundCombine"); //Create frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Close the frame when |x| button is pressed
//Add components to the frame
JButton button = new JButton();
frame.getContentPane().add(button, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
}
Run Class:
public class Run {
public static void main(String args[]){
new Main();
}
}
However, I've also seen this method of starting JSwing applications:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
What is the big difference between the two? What sort of problems would I encounter down the road by using either one of the two. Although there are many different ways to write the same program, I want to know the conventional way of going about this.
Thanks!
You're asking what's the difference between an orange and a buffalo -- these are two completely different things.
The main method is the entry point of all Java programs, even those without main methods such as applets where there actually is a main method, but it's hidden from view.
The run method you speak of is a method that needs to be part of any class that implements a Runnable interface. This is not the entry point for programs to start.
Your example above, that is to feed a Runnable into the SwingUtilities.invokeLater(...) method is a way to guarantee that the code within the Runnable's run method is called on the Swing event thread, something that you want to do when starting Swing (not JSwing) applications for thread safety purposes, since if you don't do this, there are risks of errors (actually exceptions) being thrown.
Swing applications still need a main method regardless of whether you queue them on the Swing event thread or not. It's not "either use main or run", since again, they are totally different animals.
Just because some code "works for now" is no guarantee that it will work later. Threading exceptions are notorious for occurring intermittently and when least desired.
I have this GUI application, and I want to execute a custom action inmediatelly when the user open the application, but after the GUI are shown.
So, I put the call to the action into the public Main() of the JFrame like this:
public Main() {
initComponents();
ExecuteAfter();
}
Where ExecuteAfter() is the method that contain the acction, or actions to execute.
This works fine, but not in the way I want. This way, the action executes allways before the JFrame are displayed, that is before the aplication windows appear in the screen. What I want is that execute the action only after the JFrame are displayed, that is after the aplication windows appear in the screen.
I tried put the call into the public static void main(String args[]) because there's where the JFrame is created and displayed. But doesn't work because the method isn't static, and I can't put static that method because it use some components of the JFrame that are already initialized non-static by the IDE.
So, the question is: Where I need to put the call for the action can be executed after the JFrame are displayed on the screen? Or there's other way of doing that?
Thanks in advance!
I used a WindowListener and solved the problem.
Instead of put the call in the constructor public Main() or in the main public static void main(String args[]) which cannot be done, I configured a WindowsListener for do the call. Like that:
private void formWindowOpened(java.awt.event.WindowEvent evt) {
ExecuteAfter();
}
And works perfectly in the way I want.
Thanks #MadProgrammer for the tip.
If i understand you question, I use a similar case for my project. I was needed to start timer when JFrame show, so this is how i do that.
So i use 2 methods and 1 constructor. First method (exp. Name: prepare GUI), here you can add all thinks what you need to create JFrame, JPanel....and that method I call in constructor. In second method (exp. Name: start GUI) you will add all components to JPanel/s, JPanel/s to JFrame, and set JFrame visible = (true) and then add your method ExecuteAfter(). That second method(prepare GUI) you need to call in main method. I hope that's will help you.
I have some initialization code that needs to be run when my Java Swing application starts, without any events being triggered.
My initialization code is in the myInits() function. myInits() does all sorts of thing: reads config from a file, sets the background and some labels, spawns network threads, initializes variables.
From googling and my own knowledge i have figured out different ways to achieve this(please correct me if any of the assumptions stated below are wrong):
Run myInits() when the Window_Opened event is triggered.
This makes sure the GUI is painted and myInits() can access any component and change it. Unfortunately I can't use this method because my application starts hidden and Window_Opened doesn't get triggered.
Put myInits() inside the JFrame constructor:
public class MyFrame extends javax.swing.JFrame {
private MyFrame(){
initComponents(); // <= Auto generated by NetBeans GUI Builder
myInits();
}
}
I suppose there's nothing wrong with this methoed because initComponents() itself does all kinds of GUI manipulation. I used this method and it worked just fine.
But today I changed MyFrame into a Singleton and i got a java.lang.ExceptionInInitializerError. Because myInits() calls MyFrame.getInstance() and by putting it in the constructor I'm technically calling getInstance() inside another getInstance(). I tried making getInstance() synchronized but it didn't work.
Make myInits() public and call it from main() :
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new ChatFrame().myInits();
}
});
}
I personally don't like this method because i don't want myInits() to be public. Also because I like number 4 better.
invokeLater myInits() in the constructor.
private myFrame(){
initComponents();
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
myInits();
}
});
}
This is what i myself came up with. Because the instantiation itself is being done in an invokeLater() method(see number 3), I figured I could be sure that myInits() will run after new myFrame(); has finished and i can safely call MyFrame.getInstance().
To sum it up:
1) Are all of these methods correct?
2) Is any of these (or other possible methods i may have not mentioned) considered the best practice?
3) Which one is the best practice for a Singleton JFrame?
4) Why when i synchronized my getInstance() method i still got the java.lang.ExceptionInInitializerError?
In my opinion, if your initialization logic in not ui specific, it should be in main. Extract a separate class out of myinit, and call it in main.
You may also make it singleton using enum, and use it, so that it gets initialized upon first use/ application load.
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 need help in my Java applet.
import java.awt.*;
import java.applet.*;
public class Screen extends Applet{
public void init(){
setSize(300,300);
setBackground(Color.BLACK);
}
}
This error keeps popping up when I run it.
Exception in thread "main" java.lang.NoSuchMethodError: main
You are trying to run the applet as an application using
java Screen
That won't work, because an applet is not an application, and doesn't normally have a main() method, which is what java Screen will try to run.
There are a few solutions:
Run it using the appletviewer tool, which comes with the JDK.
Run it in the browser by embedding it in an HTML page.
Make it an "app-applet".
It's been almost ten years since I've actually written an applet so I don't remember the details around #3, but IIRC it involves adding a main() method to the applet and having that main() method launch the applet. I'm sure you can find it on Google.
Create a new swing form. Since your class extends the default 'applet' you can simply add it to a swing application like this Screen x = new Screen(); then add it to your JFrame YourJframe.add(x); Hope this helped! (I could use an upvote lol :))