Why does my GUI fail to appear on the page? - java

import javax.swing.*;
import java.awt.*;
public class Grid extends JFrame{
public Grid(){
super("Pathfinding Algorithms");
setContentPane(new drawGrid());
setSize(1920,1080);
setExtendedState(JFrame.MAXIMIZED_BOTH);
setUndecorated(true);
setVisible(true);
}
class drawGrid extends JPanel {
public void paintComponent(Graphics g){
g.setColor(Color.BLACK);
g.drawLine(0,50,1920,50);
}
}
public static void main(String[] args){
new Grid();
}
}
For some reason, nothing is being displayed whenever I run this code. I receive no errors and I get no output messages.
How can I fix this?

Follow a tutorial to learn the basics of Swing. Oracle provides one free-of-cost.
There you will find this example code to compare to your code.
In that example code you’ll find the main method makes this call:
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
Swing thread
Every Swing app has a thread dedicated to the GUI, the event dispatching thread (EDT) thread mentioned here in the Comments. Drawing, tracking the user's inputs with mouse and keyboard, responding to window dragging/resizing, and all other on-screen work must be performed on that thread dedicated to Swing.
In contrast, you code is running on the main thread.
That invokeLater call seen above is a way to get your GUI creation code to run on the Swing thread. So you could modify your code like this:
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Grid() ;
}
});
However, I suggest you study that tutorial and other examples for better ways of how to work with Swing. For example, it is generally best to avoid doing work unnecessarily in constructors as seen in your code snippet. And pay attention to issues listed in Comment by Andrew Thompson.
By the way, Swing is fully supported but is in maintenance-mode.
You may want to consider the alternative, JavaFX (OpenJFX). JavaFX is being actively developed, with a release every six months synchronized to Java releases. Development is led by the Gluon company in cooperation with Oracle Corp. as a sub-project on the OpenJDK project.
Same threading rules apply to JavaFX, where a thread is dedicated to the GUI. Never access or manipulate a GUI widget in either Swing or JavaFX/OpenJFX from another thread.

Related

Thread.sleep() not working as it should [duplicate]

public class TestFrame extends JFrame
{
public TestFrame()
{
setBounds(10, 10, 500, 500);
setLocationRelativeTo(null);
setDefaultCloseOperation(3);
}
public static void main(String[] args) throws InterruptedException
{
TestFrame tf = new TestFrame();
tf.add(new JButton("test1"));
tf.setVisible(true);
Thread.sleep(2000);
tf.getContentPane().removeAll();
tf.add(new JButton("test2"));
System.out.print("Show test");
}
}
I want the program show JButton("test2") after 2 seconds.
Then I add thread.sleep(2000) after test1.
But I don't know why the program stops at showing the test1 JButton,
not showing test2 JButton and the "show test" message can sucess print out
Short answer, don't.
Swing is a single threaded framework, this means that any thing that blocks the Event Dispatching Thread will prevent it from updating the UI or processing any new events (making your UI look like it's hung, cause it has).
Sure, you could use a Thread, but Swing is also not thread safe. This means that ALL modifications to the UI MUST be made from within the context of the Event Dispatching Thread. While there are ways to overcome this, the easiest way is to simply use a Swing Timer.
Take a closer look at How to use Swing Timers and Concurrency in Swing for more details
You should also take a look at Initial Threads.
When updating the UI, it may be required to call revaldiate and repaint after you have added the new components to force the UI to update to re-layout it's contents.

What is the difference and efficiency between main() and run()?

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.

Lag before JFrame event handlers are added?

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.

Why does my boilerplate Java desktop app JFrame use EventQueue.invokeLater in the main method?

I am using the latest Eclipse, and GWT Designer, to make a swing application in Java.
The main function in my application window (which is a javax.swing.JFrame) in the auto generated by the tools looks like this:
/* launch the application */
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
AppWindow window = new AppWindow();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
This seems like a lot of noise around what could have been just this:
public static void main(String[] args) {
try {
AppWindow window = new AppWindow();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
I have read that the EventQueue.InvokeLater technique is required in some situations, and another question asks where to use it here.
My question is simpler; Why do this automatically in the code generator here? Why should main return quickly and let the application window get created later by the event queue? Wouldn't blocking be exactly the point? Why is the JFrame auto-generated designer doing this EventQueue stuff? I have tried to see some difference in the start up and showing of forms whether this code is done the simpler way or the harder way, and I can only conclude provisionally that this has some benefits that are not visible in tiny demo apps made by beginners like me, and that perhaps in real-world large complex Jframe based classes, there is some benefit to this delaying/queuing strategy?
Depending on your application and how it's being used, it's possible that there could be something that is drawing on the screen (and thus using the EventQueue) before or during the call to your main method. Calls that modify any UI components should be made on the Event Dispatch Thread, and this includes setting the application visible.
So just to be safe, it's a good practice to start your application on the EDT.
Why do this automatically in the code generator here?
It won't hurt, it's easy to generate, and it's considered good practice.
Why should main return quickly and let the application window get created later by the event queue?
It's possible that the main method is being called from some other application that is using the EDT and may have already drawn something on screen. If you draw your application directly in main, it's possible that your application may be altering some component that is in the process of being handled by something on the EDT, and potentially already drawn on the screen.
So just to be safe in case this situation ever happens, you should leave it up to the EDT to draw your application so it can do it when it won't interfere with anything else.
Wouldn't blocking be exactly the point?
Unless something else is calling main other than the JVM process that your user started by double-clicking the desktop icon, it's not going to make a difference when main returns as long as there is something on the screen.
I can only conclude provisionally that this has some benefits that are not visible in tiny demo apps made by beginners like me
You're right - most of the time it's probably not gonna make a difference, but I presume they included it because it was easy to generate & implement, it can't hurt, and it would exemplify good practice.
1) why is building Swing GUI inside try-catch-finally, I can't see any reason(s) for that, split create non thread safe GUI and non thread safe code to the separates threads,
2) Swing isn't thread safe, then correct is in all cases that pack() + setVisible(true) would be
last GUI rellated code lines
wrapped into invokeLater
forgot for examples from some code ExamplesDepots, this forum, another forums, sure these code works, but with risk that whatever/everything could happen
correct Swing GUI launch
for example
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
AppWindow window = new AppWindow();
window.frame.setVisible(true);
}
});
}
3) is there some Serializable, Custom L&F then (better would be) wrap into invokeAndWait

Main Thread vs. UI Thread in Java

In many Swing snippets given here as answers, there is a call to SwingUtilities#invokeLater from the main method:
public class MyOneClassUiApp {
private constructUi() {
// Some Ui related Code
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new MyOneClassUiApp().constructUi();
}
});
}
}
But according to the Threads and Swing article, it is safe to construct UI from main thread:
A few methods are thread-safe: In the Swing API documentation,
thread-safe methods are marked with this text:
This method is thread safe, although most Swing methods are not.
An application's GUI can often be constructed and shown in the main
thread: The following typical code is safe, as long as no components
(Swing or otherwise) have been realized:
public class MyApplication {
public static void main(String[] args) {
JFrame f = new JFrame("Labels");
// Add components to
// the frame here...
f.pack();
f.show();
// Don't do any more GUI work here...
}
}
So, is there a real (thread safety) reason to construct the UI in main through SwingUtilities#invokeLater, or this is just a habit, to remember do it in other cases?
"The Swing single-thread rule: Swing components and models should be created, modified, and queried only from the event-dispatching thread."—Java Concurrency in Practice, also discussed here and here. If you don't follow this rule, then you can't reliably construct, modify or query any component or model that may have assumed that you did follow the rule. A program may appear to work correctly, only to fail mysteriously in a different environment. As violations may be obscure, verify correct usage by using one of the approaches mentioned here.
I think that using SwingUtiltities.invokeLater() is just an easier way to execute some code asynchronously. Sometimes it is required for certain application: for example you can create 2 separate windows simultaneously. Nothing more.
It's safe to create your Swing UI in the main method because how would other components be displayed before you set up your UI? As long as you haven't thrown some stuff on the screen already you'll be fine. In other words, this would be bad:
public class MyApplication
{
public static void main(String[] args)
{
JFrame f = new JFrame("Labels");
// Add components to
// the frame here...
f.pack();
f.show();
// now make another frame:
JFrame f2 = new JFrame("Labels2");
// Add components to the 2nd frame here...
f2.pack();
f2.show();
}
}
If you did the above you'd have JFrame f up and running then you'd be adding Swing UI components off the Event Dispatch Thread (EDT). invokeLater runs the code on the EDT - it won't hurt to use it if you want extra peace of mind.

Categories