Consider the two classes and could you offer an explanation on the difference between them.. I know the first creates an object of the class but that is not my concern...
Specifically the block of code including and below the line with,
**javas.swing.swingUtiliies.invokeLater(new Runnable() {
//also both import javax.swing
public class HelloWorld extends JFrame{
public HelloWorld(){
super("HelloWorldSwing");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel label = new JLabel("Hello World");
getContentPane().add(label);
pack();
setVisible(true);
}
public static void main(String[] args) {
HelloWorld h = new HelloWorld();
}
}
public class HelloWorldSwing {
private static void createAndShowGUI() {
JFrame frame = new JFrame("HelloWorldSwing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel label = new JLabel("Hello World");
frame.getContentPane().add(label);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
}
The second example upholds the rule to execute all GUI-related code on the Event Dispatch Thread, which is achieved by passing a Runnable with said code to the invokeLater method.
By "GUI-related code" I mean instantiating any AWT/Swing classes, calling any methods on them or accessing any properties.
Related
I'm want to run my gui, but I don't really know how to initialize this class. I'm transitioning from python to Java, so I'm still fairly new to this. The code works, I just need to know how to run it.
import javax.swing.*;
import java.awt.*;
// Where the main run function for the application will lie
public class MainWindow extends JFrame{
public void init(){
// Initial window
JFrame startFrame = new JFrame("P.D");
startFrame.setSize(1200, 800);
startFrame.setVisible(true);
startFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Panel to hold our buttons
JPanel startPanel = new JPanel();
startFrame.add(startPanel);
// Button to initialize everything
JButton startButton = new JButton("Start");
startPanel.add(startButton);
startFrame.setLayout( new GridBagLayout() );
startFrame.add(startButton, new GridBagConstraints());
// Take out the border around the text
startButton.setFocusable(false);
}
public static void main(String[] args) {
}
}
How do I run the init() method under static void main(String[] args?
suppose you just create a new MainWindow object in main method and call the init() method.
public static void main(String[] args){
new MainWindow().init();
}
You can also run the function by making it static.
Like python "static method".
public static void init(){
..
And:
public static void main(String[] args) {
init();
}
You can implement constructor instead of init() method and you can start gui like below
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new MainWindow().setVisible(true);
}
});
}
Upon running the project, Java shows up on my dock but doesn't run at all. It stays there for about 5-10 seconds and disappears. Is there something wrong with the code or my Mac?
import javax.swing.JFrame;
public class Test extends JFrame {
public Test() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(600,600);
this.setVisible(true);
this.setResizable(false);
this.setTitle("Test");
}
It has nothing to do with being on a Mac.
Add this to your main function (which could be in Test.java or in any other class) in order to create a GUI thread and instantiate your Test JFrame class.
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Test();
}
});
}
Calling new Test(); is all you need to do, however doing it inside javax.swing.SwingUtilities.invokeLater is very important for the future of your application as it allows you do to other things in the background and at the same time, which will remove any visible latency. This is what Java itself recommends to do.
You will need to import javax.swing.SwingUtilities; or just do import javax.swing.*;.
You need to call somewhere the instance of test in order to work..
public class Test extends JFrame {
private static final long serialVersionUID = -2949102464273156555L;
public Test() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(600, 600);
this.setVisible(true);
this.setResizable(false);
this.setTitle("Test");
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Test();
}
});
}
}
I'm reading Thinking in Java and the author stresses that main method shouldn't call swing methods. As an example of that practice he presents the following piece of code (available on his webpage):
//: gui/SubmitSwingProgram.java
import javax.swing.*;
import java.util.concurrent.*;
public class SubmitSwingProgram extends JFrame {
JLabel label;
public SubmitSwingProgram() {
super("Hello Swing");
label = new JLabel("A Label");
add(label);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(300, 100);
setVisible(true);
}
static SubmitSwingProgram ssp;
public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(new Runnable() {
public void run() { ssp = new SubmitSwingProgram(); }
});
TimeUnit.SECONDS.sleep(1);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ssp.label.setText("Hey! This is Different!");
}
});
}
} ///:~
The gui object is then created and initialized through invokeLater method making it thread safe. But few pages later the author presents the following code:
//: gui/Button2.java
// Responding to button presses.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import static net.mindview.util.SwingConsole.*;
public class Button2 extends JFrame {
private JButton
b1 = new JButton("Button 1"),
b2 = new JButton("Button 2");
private JTextField txt = new JTextField(10);
class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
String name = ((JButton)e.getSource()).getText();
txt.setText(name);
}
}
private ButtonListener bl = new ButtonListener();
public Button2() {
b1.addActionListener(bl);
b2.addActionListener(bl);
setLayout(new FlowLayout());
add(b1);
add(b2);
add(txt);
}
public static void main(String[] args) {
run(new Button2(), 200, 150);
}
} ///:~
where SwingConsole is:
//: net/mindview/util/SwingConsole.java
// Tool for running Swing demos from the
// console, both applets and JFrames.
package net.mindview.util;
import javax.swing.*;
public class SwingConsole {
public static void
run(final JFrame f, final int width, final int height) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
f.setTitle(f.getClass().getSimpleName());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(width, height);
f.setVisible(true);
}
});
}
} ///:~
So contrary to the previous example an object implementing JFrame is created and initialized within the main method / main thread.
My question is then:
(1) Is the second example wrong or is the first one exaggerated?
(2) Is it enough that I call swing methods through invokeLater only after the setVisible call and before that statement it is safe to call swing methods within main thread?
The second example is wrong. Swing components must be created and used from the event dispatch thread. See https://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html.
Quote from the javadoc:
Calls to an application's main method, or methods in Applet, are not invoked on the event dispatching thread. As such, care must be taken to transfer control to the event dispatching thread when constructing and showing an application or applet.
(emphasis mine)
The example with the main() method might be a bit misleading. The rule AFAIK is that only the main thread is allowed to execute Swing updates/redraws etc. and the main() method per definitionem is the main thread. All other threads are required to schedule stuff via SwingUtilities.invokeLater(...). It might be that even for the main thread it improves latencies since you might do time consuming stuff in the main thread and schedule GUI refreshes foe whenever the main thread is less busy.
EDIT: Proven Wrong
I have this project that I need to publish, but don't know which way will be best. Can somebody help me please.
I have a Gui application(Jframe). In there I have a Jpanel that contains some animations (implement runnable). So in my main method I would call the constructor first, so everything display nicely, then called Runner.start(). (Thread)
So basically the gui pop up and then the animation happens, to be specific the animation is just the title of my program that slides in.
Now I want to put this on the website so my students can use.
I do not want to use java web start, i want this to act as an applet.
So do i put this jframe into my applet?
or should I convert this whole thing from jframe to japplet? and is this applet need to implement Runnable?
The thing that bug me is that Japplet has no main method, so how can I specified when my Jpanel can execute its animation? I want the animation to occur after everything has load up on the screen, not before.
I guess put it as the last statement of init() method? Correct me if I am wrong.
Thanks,
I have a Gui application(Jframe). .. I want to put this on the website so my students can use.
While it is possible to convert the frame to an applet, a better option is to launch the frame from a link using Java Web Start.
you can do both:
MainGui
import java.awt.BorderLayout;
import javax.swing.*;
public class MainGui extends JPanel {
public MainGui() {
this(null);
}
public MainGui(MyJApplet applet) {
this.applet = applet;
if (!isApplet()) {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
} else
frame = null;
setLayout(new BorderLayout());
// setPreferredSize(new Dimension(640, 480));
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MainGui.this.run();
}
});
}
String title() {
return "Title";
}
public void addContent() {
add(new JLabel("add content! top"));
}
void run() {
if (isApplet()) addContent();
else {
frame.setTitle(title());
frame.getContentPane().add(this, BorderLayout.CENTER);
addContent();
frame.pack();
System.out.println(getSize());
frame.setVisible(true);
}
}
boolean isApplet() {
return applet != null;
}
public static void main(String[] args) {
new MainGui(null);
}
protected final JFrame frame;
protected final MyJApplet applet;
private static final long serialVersionUID = 1;
}
MyJApplet
import java.awt.BorderLayout;
import javax.swing.JApplet;
public class MyJApplet extends JApplet {
public void start() {
}
public void init() {
getContentPane().setLayout(new BorderLayout());
addContent();
}
public void addContent() {
getContentPane().add(new MainGui(this), BorderLayout.CENTER);
}
public static void main(String[] args) {
new MainGui(null);
}
private static final long serialVersionUID = 1;
}
I wish to display my gui in the main method however it doesn't seem to do so...
I've used the suggestion here:
jformdesigner design it won't display?
But that did not work,
My error at the moment is that eclipse is suggesting I need to create a method called setDefaultCloseOperation which is already defined in the class and the same for the setvisible.
"The method setDefaultCloseOperation(int) is undefined for the type bmicalc
The method setVisible(boolean) is undefined for the type bmicalc"
main method:
import java.awt.Container;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.WindowConstants;
public class iu {
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
bmicalc GUI = new bmicalc();
GUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GUI.setVisible(true);
}
});
class bmicalc extends JFrame{
public bmicalc() {
initComponents();
}
private void initComponents() {
JFrame bmiCalculatorFrame = new JFrame();
{
bmiCalculatorFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
bmiCalculatorFrame.setTitle("BMI Calculator");
Container bmiCalculatorFrameContentPane = bmiCalculatorFrame.getContentPane();
bmiCalculatorFrameContentPane.setLayout(new GridLayout());
}
}}}}
Your bmicalc class should extend JFrame, but it is not. setDefaultCloseOperation and setVisible methods belong to JFrame.
Also, it is not very clear, but it looks like the JFormDesigner generated another JFrame.
EDIT:
Here is a example of JFrame generated by JFormDesigner:
public class TestFrame extends JFrame {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
TestFrame frame = new TestFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
public TestFrame() {
initComponents();
}
private void initComponents() {
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
//======== this ========
Container contentPane = getContentPane();
contentPane.setLayout(new FormLayout(
"default",
"default"));
pack();
setLocationRelativeTo(getOwner());
// JFormDesigner - End of component initialization //GEN-END:initComponents
}
// JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables
// JFormDesigner - End of variables declaration //GEN-END:variables
}
EDIT - according to the last question edit
To address your compilation issues see the snippet below. However, it is not clear what are you trying to achieve with JFrame bmiCalculatorFrame.
class bmicalc extends JFrame{
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
bmicalc GUI = new bmicalc();
GUI.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
GUI.setVisible(true);
}
});
}
public bmicalc() {
initComponents();
}
private void initComponents() {
//............
}
}