Swing GUI one simple thing - java

I have one simple question why do I need write code like this with
SwingUtilities.invokeLater(new Runnable(){
If programm create same frame without it?
code with SwingUtilities
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class App {
public static void main (String args[]){
SwingUtilities.invokeLater(new Runnable(){
public void run() {
JFrame frame = new JFrame("Hello world swing");
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 400);
}
});
}
}
code without swing utilities.
import javax.swing.JFrame;
public class App {
public static void main (String args[]){
JFrame frame = new JFrame("Hello world swing");
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 400);
}
}

Swing is not thread-safe, and is single-threaded. It relies on the Event Dispatch Thread (EDT) for creating, updating and rendering its components.
See http://en.wikipedia.org/wiki/Event_dispatching_thread
SwingUtilities.invokeLater and SwingUtilities.invokeAndWait are utility methods
to basically put your Swing related task into the EDT.
If you don't do it, it may fail eventually. You will see weird results, as your application becomes bigger.
Always do GUI (SWING) related operations on EDT.
Also most GUIs are single-threaded. So is Swing. Therefore, trying to
access Swing from more than one thread will increase the risk of application failing.
Read this
http://codeidol.com/java/java-concurrency/GUI-Applications/Why-are-GUIs-Single-threaded/
In your code, a Swing Operation (creation of JFrame) is being done on main thread, which is not recommended. Use SwingUtilities.invokeLater().

Related

Java.awt.EventQueue.invokeLater() : Can't understand the syntax

I understand that EventQueue.invokeLater() is a function called to make the Java Swing components Thread-Safe.
Also, I know that the argument to this function is an object with implements Runnable.
However, I am unable to understand the syntax for this function call, i.e. this call -
EventQueue.invokeLater(()-> {
new Screen();
});
Here, Screen() is a class that extends JFrame.
public class Screen extends JFrame
{
Screen()
{
setSize(1000, 1000);
JPanel j1 = new Board();
j1.setBounds(0,0,500, 500);
JPanel j2 = new DiceModel();
j2.setBounds(500, 0, 500, 500);
add(j1);
add(j2);
setLayout(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args)
{
EventQueue.invokeLater(()-> {
new Screen();
});
}
}
This code runs as expected.
Board and DiceModel are two classes I have defined that which extend JPanel.
The invocation
EventQueue.invokeLater( new Screen() );
gives the expected error that Screen is not an object of type Runnable.
So,my question is, what is the meaning of the syntax for the function call for invokeLater() ?
Is it a kind of anonymous function call in Java ?
The complete Swing processing is done in a thread called EDT (Event Dispatching Thread). Therefore you would block the GUI if you would compute some long lasting calculations within this thread.
The way to go here is to process your calculation within a different thread, so your GUI stays responsive. At the end you want to update your GUI, which have to be done within the EDT. Now EventQueue.invokeLater comes into play. It posts an event (your Runnable) at the end of Swings event list and is processed after all previous GUI events are processed.
Also the usage of EventQueue.invokeAndWait is possible here. The difference is, that your calculation thread blocks until your GUI is updated. So it is obvious that this must not be used from the EDT.
Still there is Java code out there that starts a JFrame simple from the main thread. This could cause issues, but is not prevented from Swing. Most modern IDEs now create something like this to start the GUI
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new NewJFrame().setVisible(true);
}
});
}

What is the prefered method for opening starting a swing interface and what's difference? [duplicate]

This question already has answers here:
Extends JFrame vs. creating it inside the program
(6 answers)
Closed 7 years ago.
so I've found multiple ways of implementing a swing GUI in java but don't know what each does and my teacher isn't able to help me. One method of creating a JFrame is:
import javax.swing.*;
import java.awt.*;
public class UI extends JFrame{
public UI() {
initaliseGUI();
}
private void initaliseGUI(){
setTitle("My Title");
setBackground(Color.red);
setSize(800,500);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args){
EventQueue.invokeLater(new Runnable(){
#Override
public void run(){
UI M = new UI();
M.setVisible(true);
}
});
}
But another way of implementing it is:
import javax.swing.*;
import java.awt.*;
public class Main{
public static void main(String[] args){
JFrame window = new JFrame();
window.setSize(500,500);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container c = window.getContentPane();
c.setBackground(Color.red);
window.setBackground(Color.red);
window.setTitle("main");
JLabel message = new JLabel("JLabel");
window.add(message);
window.setVisible(true);
}
}
what is the difference between how each one works and when should I use one over the other and how does the runnable work in this context?
thankyou!
Your first example calls the EventQueue invokeLater method, but extends a JFrame.
Your second example puts everything in the static method main, and doesn't run the invokeLater method.
Here's one way I start a Swing application.
public class TryingProject2 implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new TryingProject2());
}
#Override
public void run() {
JFrame frame = new JFrame("Color Gradient Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel());
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createMainPanel() {
JPanel panel = new JPanel();
// Add your Swing components here
return panel;
}
}
I don't extends Swing components. I use Swing components. The only time you extend a Swing component, or any Java class, is when you want to override one of the class methods.
The SwingUtilities invokeLater method is the same as the EventQueue invokeLater method. This method puts the creation and updates of all Swing components on the Event Dispatch thread.
I implement Runnable because it makes the invokeLater method parameter an instance of the class.
I create the main panel in a method to keep the JFrame code separate from the JPanel(s) code.

Best practice to start a swing application

What is the best practice way to start a java swing application? Maybe there is another way to do it.
I want to know if i have to use the SwingUtilities class to start the application (secound possibility) or not (first possibility).
public class MyFrame extends JFrame {
public void createAndShowGUI() {
this.setSize(300, 300);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
// add components and stuff
this.setVisible(true);
}
public static void main(String[] args) {
// First possibility
MyFrame mf = new MyFrame();
mf.createAndShowGUI();
// Secound possibility
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
MyFrame mf = new MyFrame();
mf.createAndShowGUI();
}
});
}
}
Only the second way is correct. Swing components must be created and accessed only in the event dispatch thread. See concurrency in swing. The relevant quote:
Why does not the initial thread simply create the GUI itself? Because almost all code that creates or interacts with Swing components must run on the event dispatch thread. This restriction is discussed further in the next section.
So yes, you need to use invokeLater().

JFrame memory leak

I've created a new project in java with this simple code:
public static void main(String[] args)
{
JFrame frame;
frame = new JFrame("Empty");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
I've noticed that moving the JFrame causing the memory used by the process to increase.
Why is that?
Is there a way to avoid this using the same code above but with some additions?
Are there any better ways to simply display a JFrame?
Seeing memory usage increase does not mean that there's a memory leak. The program may use more memory because it has to create temporary objects for event dispatching or repainting. These temporary objects are short-lived and are removed by the garbage collector in a short period of time; so the memory used by them becomes available for the program again.
You won't see this with process monitoring tools though since the memory is not returned to the OS; the JVM reserves it for future use. You can use tools like VisualVM to monitor the actual memory use of the program.
Are there any better ways to simply display a JFrame?
The code that you post is actually incorrect; you shouldn't create and manipulate GUI objects from the program's main thread. Here's a correct example of displaying a JFrame from the Java Tutorial:
import javax.swing.*;
public class HelloWorldSwing {
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("HelloWorldSwing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Add the ubiquitous "Hello World" label.
JLabel label = new JLabel("Hello World");
frame.getContentPane().add(label);
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}

Why doesn't the EDT shut down when all live threads are daemon?

The following code slides a card across the screen. When I shut down the main window, I expect the event dispatch thread to shut down as well, but it does not. Any ideas on why the ScheduledExecutorService thread prevents the EDT from shutting down?
import java.awt.Graphics;
import java.net.URL;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Main extends JPanel
{
private float x = 1;
public void next()
{
x *= 1.1;
System.out.println(x);
repaint();
}
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
URL url = getClass().getResource("/209px-Queen_of_diamonds_en.svg.png");
g.drawImage(new ImageIcon(url).getImage(), (int) x, 50, null);
}
public static void main(String[] args)
{
JFrame frame = new JFrame();
final Main main = new Main();
frame.getContentPane().add(main);
frame.setSize(800, 600);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(true);
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1, new ThreadFactory()
{
public Thread newThread(Runnable r)
{
Thread result = new Thread(r);
result.setDaemon(true);
return result;
}
});
timer.scheduleAtFixedRate(new Runnable()
{
public void run()
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
main.next();
}
});
}
}, 100, 100, TimeUnit.MILLISECONDS);
}
}
The default behaviour when you close a JFrame is simply to hide it, not to cause the application to exit. You need to call:
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
In other words: This has nothing to do with the ScheduledExecutorService; It is to do with the fact that the Event Dispatch thread is not a daemon thread.
ADDITIONAL
Rather than use a ScheduledExecutorService which in turn calls SwingUtilities.invoke... you should consider using javax.swing.Timer, which will fire ActionEvents periodically directly on the Event Dispatch thread, hence making your code simpler / more compact and removing the need for the additional thread.
Also, you are recreating the ImageIcon on every animation frame which will be very inefficient, particularly in a tight animation loop. Far better to create it once when the application starts.
Your thread factory is correct. If you set EXIT_ON_CLOSE on the frame then it will exit.
However, consider using a library such as Trident instead.
I ran across the answer in this excellent blog post: http://www.pushing-pixels.org/?p=369
With the current implementation, AWT terminates all its helper threads allowing the application to exit cleanly when the following three conditions are true:
There are no displayable AWT or Swing components.
There are no native events in the native event queue.
There are no AWT events in java EventQueues.
[...]
In the current implementation this timeout is 1000 ms (or one second). What this effectively means that AWT is not shutdown immediately after disposing the last window in your application and processing all pending events. Instead, it wakes every second, checks for any pending or processed events during the sleep and continues sleeping if there have been any such events.
The author goes on to say that his code posts an event to the EDT every 100ms in spite of the fact that the associated Window is no longer visible. This is exactly what happens in my case as well! The ScheduledExecutorService is posting events into the EDT, which in turn prevents AWT from shutting down, which in turn means that the ScheduledExecutorService will keep on posting more events.
As an aside, I am surprised by the number of people that recommend the use of JFrame.EXIT_ON_CLOSE. Each to his own I guess, but I recommend you read http://findbugs.sourceforge.net/bugDescriptions.html#DM_EXIT
I think that, rather than using daemon threads in your ScheduledExecutorService, you'd better explicitly shut it down when the user wants to quit.
You can do that by adding a WindowListener to the main frame:
public static void main(String[] args)
{
JFrame frame = new JFrame();
final Main main = new Main();
frame.getContentPane().add(main);
frame.setSize(800, 600);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.setVisible(true);
final ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(new Runnable()
{
public void run()
{
// NOTE that you don't need invokeLater here because repaint() is thread-safe
main.next();
}
}, 100, 100, TimeUnit.MILLISECONDS);
}
// Listen to main frame closure and shut down timer
main.addWindowListener(new WindowAdapter()
{
public void windowClosed(WindowEvent e)
{
timer.shutdownNow();
}
});
}
Note the changes I've made to your snippet:
timer is now declared final (needed
as it is referenced by an inner
anonymous class)
There is no more ThreadFactory passed to newScheduledThreadPool
I have removed the
use of invokeLater for calling
main.next() because the only Swing
call made there is repaint() which
is one of the few Swing methods that
are thread-safe.
Please note that I haven't tried the code above, it should compile and I think it should also solve your problem. Try it and let us know!

Categories

Resources