How to hide window - java

I have two jframe windows and I want to hide the NewJFrameSplash window after a while but I am having trouble succeeding with setVisible(true)
What can I be doing wrong?
as the code shows I start the NewJFrameSplash window and at the end of a while start the NewJFrame and hide the NewJFrameSplash.
static NewJFrameSplash frame;
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new NewJFrameSplash().setVisible(true);
}
});
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
new NewJFrame().setVisible(true);
frame = new NewJFrameSplash();
frame.setVisible(false);
}

Don't use Thread.sleep(5000);, you run the risk of blocking the Event Dispatching Thread, or, if you're using a second thread, violating the single threaded nature of the API.
Instead, use a Swing Timer instead.
new NewJFrame().setVisible(true); is just going to make a new window and make it visible, twice. You need to use setVisible(false) on the instance of the window you've created earlier.
As a basic example...
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
NewJFrameSplash frame = new NewJFrameSplash();
frame.setVisible(true);
javax.swing.Timer timer = new javax.swing.Timer(5000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
frame.setVisible(false);
// Create next window
}
});
timer.setRepeats(false);
timer.start();
}
});
Take a look at How to use Swing Timers for more details
Swing also provides "splash screen" support. You should take a closer look at How to create a splash screen for more details

Related

Java: A Thread don't modify the GUI even with SwingUtilities.invokeLater

I have a problem with this code:
public class Gui_01 extends JFrame {
private JPanel display;
private ActionListener visualizza() {
ActionListener evento = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
display.removeAll();
Thread t = new Thread(new Runnable() {
public void run() {
JPanel visualizza = new JPanel();
visualizza.add(new JLabel("Test", SwingConstants.CENTER));
display.add(visualizza, BorderLayout.SOUTH);
updateProgress(visualizza);
}
}
);
t.start();
}
};
return evento;
}
private void updateProgress(final JPanel visualizza) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
display.add(visualizza, BorderLayout.SOUTH);
}
});
}}
I don't understand why the code don't work properly, the thread t and the thread in updateProgress work fine, but any modification to display won't affect the GUI even with invokeLater.
display.add(visualizza, BorderLayout.SOUTH)
This code don't modify the gui, i know it's normal (due to Swing), but why invokeLater don't work.
Sorry for my bad english, thanks in advance for replys.
First get rid of the display.add(visualizza, BorderLayout.SOUTH); statement in your thread. as you should never update or modify the UI from outside the context of the EDT...
Thread t = new Thread(new Runnable() {
public void run() {
JPanel visualizza = new JPanel();
visualizza.add(new JLabel("Test", SwingConstants.CENTER));
//display.add(visualizza, BorderLayout.SOUTH);
updateProgress(visualizza);
}
}
In fact, I'd discourage your from creating UI elements outside of the EDT, as you can't guarantee when they might start interacting with the UI.
Second, call revalidate and repaint after you've updated the UI...
private void updateProgress(final JPanel visualizza) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
display.add(visualizza, BorderLayout.SOUTH);
display.revalidate();
display.repaint();
}
});
}}
Swing is lazy when it comes to updating the UI, this is a good thing, as it allows you to make sweeping changes and only update the UI when you're ready to do so.
I'd also encourage you to use a SwingWorker instead, as it has functionality which you can use to synchronise the updates with the EDT. See Worker Threads and SwingWorker for more details

How to make Jlabel visible and invisible using for loop in java? [duplicate]

Hello guys I am doing a thread to update a ball over JFrame so I repaint the screen... and then paint the ball update its position .. and then draw the screen again ... draw the ball and the same cycle ... here is the code
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
Thread t = new Thread()
{
public void run()
{
while(true)
{
repaint();
b2.update(ob,2);
b2.paint(ob.getGraphics());
b2.setT(b2.getT() + 1);
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
System.out.println("Error in Sleeping");
}
}
}
};
t.start();
}
but the problem is that I don't see the ball... the paint of the screen always overrides the ball and the ball is like down under the Jframe ..
If you want to have animations in Swing, the recommended class to use is the javax.swing.Timer . This class allows you to perform operations on the Event Dispatch Thread at regular intervals.
The Swing Timer tutorial
An animation example posted here on SO (which is linked in the Swing wiki here on SO btw)
Some General Rules
Swing is not thread safe, you should only ever update UI components from within the context of the Event Dispatching Thread.
You do not control the paint process, the repaint manager does. You can request updates to occur by calling repaint, but you should never call update and paint directly when trying to update the display.
The Graphics context used by the paint sub system is a shared resource and is not guaranteed to be the same between paint cycles, you should never maintain a reference to it. You should also not rely on the results from JComponent#getGraphics this method is capable of returning null.
An Example Solution
You have a number of options, depending on what you want to ultimately achieve.
You could use a SwingWorker, but given the fact that all your going to is enter an infinite loop and it would easier to use SwingUtilities#invokeLater then actually use the publish method, this approach would actually be more work.
You could also use a Thread, but you'd end up with the same problems as using a SwingWorker
The simpliset solution, for what you're presented, is actually a javax.swing.Timer
public class Blinky {
public static void main(String[] args) {
new Blinky();
}
public Blinky() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new BlinkyPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
protected class BlinkyPane extends JPanel {
private JLabel blinkyLabel;
private boolean blink = false;
public BlinkyPane() {
setLayout(new GridBagLayout());
blinkyLabel = new JLabel("I'm blinking here");
blinkyLabel.setBackground(Color.RED);
add(blinkyLabel);
Timer timer = new Timer(250, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
blink = !blink;
if (blink) {
blinkyLabel.setForeground(Color.YELLOW);
} else {
blinkyLabel.setForeground(Color.BLACK);
}
blinkyLabel.setOpaque(blink);
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 100);
}
}
}
You can take a look at Swing Timer and Concurrency in Swing for more info
If you access GUI components outside the EDT (Event Dispatch Thread) then you might encounter strange problems, Contrary if you perform long running tasks in the EDT then also you will get problems.
Check this post for more info on GUI Threading in Java

Call a method when application closes

In my Swing chat application I have a logout button which is used to logout the user and it works fine. Now I need to logout the user when I close the Swing application window.
I did this in web application when closing browser using JavaScript, but now I need to do this in Swing application.
How can I achieve this?
Call JFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE)
Add a WindowListener to the frame.
Override the appropriate method of the listener to call your closing method, then set the frame invisible and dispose of it.
E.G.
import java.awt.*;
import java.awt.event.*;
import java.net.URI;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
class CheckExit {
public static void doSomething() {
try {
// do something irritating..
URI uri = new URI(
"http://stackoverflow.com/users/418556/andrew-thompson");
Desktop.getDesktop().browse(uri);
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
Runnable r = new Runnable() {
#Override
public void run() {
// the GUI as seen by the user (without frame)
JPanel gui = new JPanel(new BorderLayout());
gui.setPreferredSize(new Dimension(400, 100));
gui.setBackground(Color.WHITE);
final JFrame f = new JFrame("Demo");
f.setLocationByPlatform(true);
f.add(gui);
// Tell the frame to 'do nothing'.
f.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
WindowListener listener = new WindowAdapter() {
#Override
public void windowClosing(WindowEvent we) {
int result = JOptionPane.showConfirmDialog(
f, "Close the application");
if (result==JOptionPane.OK_OPTION) {
doSomething();
f.setVisible(false);
f.dispose();
}
}
};
f.addWindowListener(listener);
// ensures the frame is the minimum size it needs to be
// in order display the components within it
f.pack();
// should be done last, to avoid flickering, moving,
// resizing artifacts.
f.setVisible(true);
}
};
// Swing GUIs should be created and updated on the EDT
// http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
SwingUtilities.invokeLater(r);
}
}
Use the window events on your JFrame, there you have the Methods you might need (windowclosed();) for example. it´s the WindowListener
edit :
you can say
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
but your Windowlistener still works if you push the X (close button)
there you override the method windowClosing, with this code
public void windowClosing(WindowEvent e) {
int i = JOptionPane.showConfirmDialog(TestFrame.this, "do you really want to close?","test",JOptionPane.YES_NO_OPTION);
if(i == 0) {
System.exit(0);
}
}
this will do the work

Close JFrame from a JButton process remain alive

I have a class developed with windowbuilderpro that i want to close also from a JButton further than with the standard X button on the window, so here the example of the class :
public class MainWindow {
public JFrame frame;
public MainWindow() {
initialize();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
public void show() {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
//Show the main Frame
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
When i close the window from the X button the window close correctly and the process terminate.
When i close instead from a JButton that have this listener :
mntmExit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//Close the application main form
frame.setVisible(false);
frame.dispose();
}
});
the frame window close correctly but the process remain alive ... Why ?
As you can see there is an AWT-Shutdown thread that start and terminate continuously, How can i achieve the same behaviour of the X button that close also the application process ?
Notes :
System.exit(0); is not suitable because it terminate the application also if there are another background running thread and i don't want that . The MainWindow class should close and release it's resource, the same behaviour that have closing the application with the X button that close the MainWindow instance but if there are background thread running it doesn't kill they but wait until they finished their work...
Enviroment :
JDK 7
Eclipse 3.7.1
not sure what you really needed, that looks like that you create new JFrame again an again, don't do that, create JFrame once and re-use this Container
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // do nothing
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); // same as setVisible(false)
then for visibily you can only to call frame.setVisible(true);
for more Confortable is override WindowListener, then you can control some Events
All threads in this code stop when either the x button or the Exit button are activated. Are you getting different behavior?
import java.awt.event.*;
import javax.swing.*;
public class MainWindow {
public JFrame frame;
JButton mntmExit = new JButton("Exit");
public MainWindow() {
frame = new JFrame("Close Me!");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
mntmExit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//Close the application main form
frame.setVisible(false);
frame.dispose();
}
});
frame.add(mntmExit);
frame.pack();
show();
}
public void show() {
//Show the main Frame
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MainWindow mw = new MainWindow();
mw.show();
}
});
}
}
Just add one line:
System.exit(0);

(Java) Appearing/Disappearing JLabel in a JPanel only disappears on resize

I'm working in Java, and I have a JPanel in a JFrame. In that JPanel, among other things, I have a JLabel that I want to make appear and disappear at will. I've tried setting visibility to true/false, adding and removing it from the JFrame and JPanel, and, having looked online, I tried validate()ing and revalidate()ing ad infinitum. What can be done here to solve this problem?
In general, calling the setVisible method is sufficient to make a Swing component to be shown or hidden.
Just to be sure that it works, I tried the following:
public class Visibility {
private void makeGUI() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JLabel l = new JLabel("Hello");
final JButton b = new JButton("Hide Label");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
l.setVisible(false);
}
});
f.getContentPane().setLayout(new BorderLayout());
f.getContentPane().add(l, BorderLayout.CENTER);
f.getContentPane().add(b, BorderLayout.SOUTH);
f.setSize(200, 200);
f.setLocation(200, 200);
f.validate();
f.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Visibility().makeGUI();
}
});
}
}
The above program is able to affect the visibility by clicking on a JButton.
Could it be a Threading Issue?
My next suspicion was that perhaps a Thread that is not on the event dispatch thread (EDT) may not be affecting the display immediately, so I added the following after initializing the JLabel and JButton.
Thread t = new Thread(new Runnable() {
public void run() {
while (true) {
b.setVisible(!b.isVisible());
try {
Thread.sleep(100);
} catch (InterruptedException e) { /* Handle exception /* }
}
}
});
t.start();
With the new Thread running, it changed the toggled the visibility of the JLabel every 100 ms, and this also worked without a problem.
Calling a Swing component off the event dispatch thread (EDT) is a bad thing, as Swing is not thread-safe. I was a little surprised it worked, and the fact that it works may just be a fluke.
Repaint the JPanel?
If the JLabel's visibility is only being affected on resizing, it probably means that the JLabel is being drawn only when the JPanel is being repainted.
One thing to try is to call the JPanel's repaint method to see if the visibility of the JLabel will change.
But this method seems to be just a band-aid to a situation, if the main cause is due to a thread off the EDT is attempting to make changes to the GUI. (Just as a note, the repaint method is thread-safe, so it can be called by off-EDT threads, but relying on repaint is a workaround than a solution.)
Try using SwingUtilities.invokeLater
Finally, probably the thing I would try is the SwingUtilities.invokeLater method, which can be called (and should only be called) from a thread running separate from the EDT, if it wants to affect the GUI.
So, the earlier Thread example should be written as:
Thread t = new Thread(new Runnable() {
public void run() {
while (true) {
try {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
b.setVisible(!b.isVisible());
}
});
} catch (Exception e1) { /* Handle exception */ }
try {
Thread.sleep(100);
} catch (InterruptedException e) { /* Handle exception */ }
}
}
});
t.start();
If the change to the GUI is indeed occurring on a separate thread, then I would recommend reading Lesson: Concurrency in Swing from The Java Tutorials in order to find out more information on how to write well-behaving multi-threaded code using Swing.
setVisible() or removing it should work fine, make sure you are doing it from the event dispatch thread though. There are utility methods in EventQueue for running blocks in that thread.
http://helpdesk.objects.com.au/java/how-do-i-update-my-gui-from-any-thread
You would need to call revalidate() on the parent JPanel if you need its components to be re-laid out.
If you can post an example that demonstrates the problem I can have a look at it for you.

Categories