Recently I asked here how to add a new JPanel to JFrame. The answer helped me to get a working code. But not I have a related question: "How can I remove an old JPanel". I need that because of the following problem.
A new JPanel appears appears when I want (either time limit is exceeded or user press the "Submit" button). But in several seconds some element of the old JPanel appears together with the component of the new JPanel. I do not understand why it happens.
I thought that it is because I have to other threads which update the window. But the first thread just add the old panel once (so, it should be finished). And in the second thread I have a loop which is broken (so, it also should be finished).
Here is my code:
private Thread controller = new Thread() {
public void run() {
// First we set the initial pane (for the selection of partner).
SwingUtilities.invokeLater(new Runnable() {
public void run() {
frame.getContentPane().add(generatePartnerSelectionPanel());
frame.invalidate();
frame.validate();
}
});
// Update the pane for the selection of the parnter.
for (int i=40; i>0; i=i-1) {
final int sec = i;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
timeLeftLabel.setText(sec + " seconds left.");
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) { }
if (partnerSubmitted) {
break;
}
}
// For the given user the selection phase is finished (either the time is over or form was submitted).
SwingUtilities.invokeLater(new Runnable() {
public void run() {
frame.getContentPane().add(generateWaitForGamePanel());
frame.invalidate();
frame.validate();
}
});
}
};
Its the same whether you do add or remove a component on a visible GUI:
panel.remove(...);
panel.add(...);
panel.revalidate();
panel.repaint();
the easiest way to remove a component (panel) from a container (frame) is to keep a reference to it, and then call Container.remove(Component) ie:
private Thread controller = new Thread() {
public void run() {
final Component panel1 = generatePartnerSelectionPanel();
// First we set the initial pane (for the selection of partner).
SwingUtilities.invokeLater(new Runnable() {
public void run() {
frame.getContentPane().add(panel1);
frame.invalidate();
frame.validate();
}
});
// Update the pane for the selection of the parnter.
for (int i=40; i>0; i=i-1) {
final int sec = i;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
timeLeftLabel.setText(sec + " seconds left.");
}
});
try {Thread.sleep(1000);} catch (InterruptedException e) {}
if (partnerSubmitted) {break;}
}
// For the given user the selection phase is finished (either the time is over or form was submitted).
SwingUtilities.invokeLater(new Runnable() {
public void run() {
frame.getContentPane().remove(panel1);
frame.getContentPane().add(generateWaitForGamePanel());
frame.invalidate();
frame.validate();
}
});
}
};
i haven't tested this code but it should work.
I had problems with requestFocusInWindow on TextField too. The trick is to not construct the components in the JPanel constructor. But, make a build method and execute following code after it has been added to the frame.
This worked for me:
frame.getContentPane().removeAll(); //or .remove(previousPanel);
frame.getContentPane().add(newPanel);
panel.buildPanel(); // panel needs a builder method
frame.revalidate(); // in- and validate in one !!
frame.pack(); //
if you want to resize, you need preferredSize(); on panel or use repaint() if you don't need to resize frame.
Roman, the problem can be solved like that:
Do this in the beginning of your run method:
final JPanel partnerSelectionPanel = generatePartnerSelectionPanel();
Then do this
frame.getContentPane().add(partnerSelectionPanel);
Before you add the new panel do this:
partnerSelectionPanel.setVisible(false);
It works. I do not know if it is a safe and/or elegant solution but it works.
Related
I am trying to learn ProgressMonitor in Java Swing.
I created this simple test code -
public class ProgressMonitorTest extends JFrame
{
private JPanel contentPane;
private ProgressMonitor progressMonitor;
private JButton button;
private static ProgressMonitorTest frame;
private static boolean isFrameReady;
public JButton getButton()
{
return button;
}
public ProgressMonitor getProgressMonitor()
{
return progressMonitor;
}
/**
* Launch the application.
*/
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
try
{
frame = new ProgressMonitorTest();
frame.setVisible(true);
isFrameReady = true;
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
while(!isFrameReady)
{
//
}
frame.getButton().addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
try
{
for(int i=0;i<=10;i++)
{
final int percent = i;
SwingUtilities.invokeAndWait(new Runnable()
{
#Override
public void run()
{
frame.getProgressMonitor().setProgress(percent * 10);
frame.getProgressMonitor().setNote("Completed " + percent*10 + "%.");
}
});
try
{
Thread.sleep(1000);
}
catch(Exception ee)
{
//
}
}
}
catch(Exception es)
{
//
}
}
});
}
/**
* Create the frame.
*/
public ProgressMonitorTest()
{
isFrameReady = false;
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
setTitle("Progress Monitor");
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
progressMonitor = new ProgressMonitor(frame, "Update in progress...", "", 0, 10);
button = new JButton("Click Here");
contentPane.add(button);
setContentPane(contentPane);
}
}
A few questions regarding this-
If I remove the isFrameReady check, the program says a NullPointerException at the line where I assign the button's action listener.
If I keep the above check, then clicking on the button does nothing.
Keeping the above check and then debugging this, I let it wait for some time before it gets to the line where the action listener. In this case, it works but immediately quits saying it can't call invokeAndWait from the event handling thread.
What am I missing in all this ? Can someone explain how to get this to work.
If I remove the isFrameReady check, the program says a
NullPointerException at the line where I assign the button's action
listener.
your use of isFrameReady ensures that you have created your frame successfully. inside your main, your posted request to event dispatch thread(EDT) using call EventQueue.invokeLater(new Runnable(){}): removing the check isFrameReady, you were going to call frame.getButton() in main thread but the frame have not been yet created by frame = new ProgressMonitorTest(); in the EDT and thus a NullPointerException occurs.
If I keep the above check, then clicking on the button does nothing.
you should understand by now, that above check is nothing to do with button click. The button is not doing anything because the GUI got freezed for violating swing's single threading rule. Put your incrementing for loop of the actionPerformed method inside another thread as the following code fragement shows and execute it from there. you will see that it works fine.
new Thread(){
public void run()
{
for(int i=0; i<10; i++)
{
//whatever you were doing.
}
}
}.start();
Keeping the above check and then debugging this, I let it wait for
some time before it gets to the line where the action listener. In
this case, it works but immediately quits saying it can't call
invokeAndWait from the event handling thread.
SwingUtitlies.invokeAndWait() blocks the current thread and waits until the EDT is done executing the task given to it. As actionPerformed() function is already running inside EDT, so calling SwingUtitlies.invokeAndWait() from the current thread:EDT would block the current thread:EDT which should not be allowed. Don't use invokeAndWait for this case. you should call SwingUtilities.invokeLater() instead.
However I don't think you will get anything until you understand Swing threading model. Read the javadoc and some internet resource. DO HAVE The book Filthy Rich Clients and try the example the book offered: You will have a greater knowledge in graphical effects then any other resource can provide.
I have a class (called Class_GUI) which has a panel with lots of buttons on it. Class_GUI has some methods that change the text and colour of the buttons.
I have also have a program with the actionPerformed method. When this is called it creates an instance of Class_GUI and repeatedly calls Class_GUI methods, changing the buttons etc.
The issue I'm having is that the buttons only display properly once the actionPerformed method has finished entirely whereas I want it to change after each Class_GUI method is called.
My attempt so far is in each Class_GUI method I do this at the end of the method:
SwingUtilities.invokeLater(Refresh_GUI);
Where Refresh_GUI is defined:
Runnable Refresh_GUI = new Runnable(){
public void run(){
frame.revalidate();
frame.repaint();
}
};
Assuming that your actionPerformed method is being called within the context of the Event Dispatching Thread, no UI updates will occur until AFTER the actionPerformed method has competed, even using SwingUtilities#invokeLater won't change that, because until the actionPerformed method exits, the EDT won't be able to continue processing (amongst other things) repaint requests.
The best you can do, is start a second thread and from within that thread, update your UI components...but, you area going to be forced to use SwingUtilities#invokeLater as you should NEVER update any UI component outside the EDT.
The advantage though, is that the thread does not need to compete in order for the EDT to start processing the repaint request
UPDATED with Example
public class SwingThreadUpdate {
public static void main(String[] args) {
new SwingThreadUpdate();
}
public SwingThreadUpdate() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new BlinkPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class BlinkPane extends JPanel {
private JLabel label;
private JButton button;
public BlinkPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridy = 0;
label = new JLabel("Blinky");
label.setBackground(Color.RED);
button = new JButton("Click me");
add(label, gbc);
gbc.gridy++;
add(button, gbc);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
button.setEnabled(false);
new Thread(new BlinkTask(BlinkPane.this)).start();
}
});
}
private void setBlink(boolean blink) {
label.setOpaque(blink);
}
private void reset() {
button.setEnabled(true);
label.setOpaque(false);
}
}
public class BlinkTask implements Runnable {
private BlinkPane blinkPane;
protected BlinkTask(BlinkPane blinkPane) {
this.blinkPane = blinkPane;
}
#Override
public void run() {
Blink blinkOn = new Blink(blinkPane, true);
Blink blinkOff = new Blink(blinkPane, false);
for (int index = 0; index < 10; index++) {
if (index % 2 == 0) {
SwingUtilities.invokeLater(blinkOn);
} else {
SwingUtilities.invokeLater(blinkOff);
}
try {
Thread.sleep(125);
} catch (InterruptedException ex) {
}
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
blinkPane.reset();
}
});
}
}
public class Blink implements Runnable {
private BlinkPane blinkPane;
private boolean blink;
public Blink(BlinkPane blinkPane, boolean blink) {
this.blinkPane = blinkPane;
this.blink = blink;
}
#Override
public void run() {
blinkPane.setBlink(blink);
blinkPane.repaint();
}
}
}
You might like to have a read through Painting in AWT and Swing for more information.
Incase your actionPerform method calls code to update buttons in a for loop you could also add the updation code in the invokeLater that way both the updation and painting code will run one by one. Invoke later will execute only after current method completes its execution so only way to ensure painting happens faster is to break your tasks into smaller peices.
First, make sure you are only accessing any GUI components from the Event Dispatch thread (via invokeLater or as part of handling a GUI event).
Second, if you change any properties of a GUI component, it should automatically post an event to repaint itself. If not you can try invoking component.repaint(). But it's critical that the changes to the component properties happen on the EDT.
A simple solution is execute the entire ActionPerformed event less task to clean the screen at the end of the event queue.
So, first it executes the cleanScreen() function because the rest of the event waits for all events finish.
AnyButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
cleanScreen(); //Modify components before action performer event
EventQueue.invokeLater( new Runnable() {
#Override public void run() {
anytask(); //Action performer event
}
});
}
});
I need to execute/display a series of events from a Arraylist to a JTextArea, however, each Event gets execute with different time. Following is a quick example of my goal:
public void start(ActionEvent e)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
jTextArea.append("Test" + "\n");
try
{
Thread.sleep(3000);
} catch (InterruptedException e1)
{
e1.printStackTrace();
}
jTextArea.append("Test1" + "\n");
}
});
}
So right now, "Test" and "Test1" display on JTextArea after whole execution is completed.
How do I make "Test" display first, then 3 secs later, display "Test1"
Thank u all in advance
invokeLater schedules the runnable to run on the Event Dispatch Thread. You shouldn't sleep within it or you will starve the dispatch thread. Try using a separate worker thread instead:
Thread worker = new Thread(new Runnable(){
public void run(){
jTextArea.append("Test" + "\n");
try {
Thread.sleep(3000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
jTextArea.append("Test1" + "\n");
}
});
worker.start();
If your tasks are time/cpu intensive, then yes, definitely use a background thread to do this such as a SwingWorker object or a Runnable run in a Thread. If however what you need to do is to stagger the display of something and all you are looking for is the Swing equivalent of Thread.sleep(3000), then your best option is to use a Swing Timer. There is an excellent tutorial on how to use these which you can find here: http://download.oracle.com/javase/tutorial/uiswing/misc/timer.html
For example:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Fu extends JPanel {
private static final int TIMER_DELAY = 600;
protected static final int MAX_COUNT = 20;
private JTextArea jTextArea = new JTextArea(10, 10);
private JButton startBtn = new JButton("Start");
private Timer timer;
public Fu() {
startBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
startAction(e);
}
});
add(new JScrollPane(jTextArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED));
add(startBtn);
}
private void startAction(ActionEvent e) {
if (timer != null && timer.isRunning()) {
// prevent multiple instances of timer from running at same time
return;
}
timer = new Timer(TIMER_DELAY, new ActionListener() {
private int count = 0;
public void actionPerformed(ActionEvent e) {
if (count < MAX_COUNT) {
count++;
jTextArea.append("Test " + count + "\n");
} else {
jTextArea.append("Done! \n");
timer.stop();
timer = null;
}
}
});
timer.setInitialDelay(0);
timer.start();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame("Foo");
frame.getContentPane().add(new Fu());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
As pointed out, this is a bad idea, as you will block the event thread.
However, understanding the reason for this is important as well. As you seem to know, all code that affects the state of Swing components needs to happen in the event handling thread (which is the reason why invokeLater and friends should always be used).
What is a bit less better known is that paining code also executes in the event handling thread. When your call to Thread.sleep is executing, it's not only blocking the event thread, it's also blocking any painting of components. This is why the full update appears to happen in one go -- the JTextArea is updated but it can't be repainted until your run method returns.
Lots of info available here: http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html
Recently I asked here how to add a new JPanel to JFrame. The answer helped me to get a working code. But not I have a related question: "How can I remove an old JPanel". I need that because of the following problem.
A new JPanel appears appears when I want (either time limit is exceeded or user press the "Submit" button). But in several seconds some element of the old JPanel appears together with the component of the new JPanel. I do not understand why it happens.
I thought that it is because I have to other threads which update the window. But the first thread just add the old panel once (so, it should be finished). And in the second thread I have a loop which is broken (so, it also should be finished).
Here is my code:
private Thread controller = new Thread() {
public void run() {
// First we set the initial pane (for the selection of partner).
SwingUtilities.invokeLater(new Runnable() {
public void run() {
frame.getContentPane().add(generatePartnerSelectionPanel());
frame.invalidate();
frame.validate();
}
});
// Update the pane for the selection of the parnter.
for (int i=40; i>0; i=i-1) {
final int sec = i;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
timeLeftLabel.setText(sec + " seconds left.");
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) { }
if (partnerSubmitted) {
break;
}
}
// For the given user the selection phase is finished (either the time is over or form was submitted).
SwingUtilities.invokeLater(new Runnable() {
public void run() {
frame.getContentPane().add(generateWaitForGamePanel());
frame.invalidate();
frame.validate();
}
});
}
};
Its the same whether you do add or remove a component on a visible GUI:
panel.remove(...);
panel.add(...);
panel.revalidate();
panel.repaint();
the easiest way to remove a component (panel) from a container (frame) is to keep a reference to it, and then call Container.remove(Component) ie:
private Thread controller = new Thread() {
public void run() {
final Component panel1 = generatePartnerSelectionPanel();
// First we set the initial pane (for the selection of partner).
SwingUtilities.invokeLater(new Runnable() {
public void run() {
frame.getContentPane().add(panel1);
frame.invalidate();
frame.validate();
}
});
// Update the pane for the selection of the parnter.
for (int i=40; i>0; i=i-1) {
final int sec = i;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
timeLeftLabel.setText(sec + " seconds left.");
}
});
try {Thread.sleep(1000);} catch (InterruptedException e) {}
if (partnerSubmitted) {break;}
}
// For the given user the selection phase is finished (either the time is over or form was submitted).
SwingUtilities.invokeLater(new Runnable() {
public void run() {
frame.getContentPane().remove(panel1);
frame.getContentPane().add(generateWaitForGamePanel());
frame.invalidate();
frame.validate();
}
});
}
};
i haven't tested this code but it should work.
I had problems with requestFocusInWindow on TextField too. The trick is to not construct the components in the JPanel constructor. But, make a build method and execute following code after it has been added to the frame.
This worked for me:
frame.getContentPane().removeAll(); //or .remove(previousPanel);
frame.getContentPane().add(newPanel);
panel.buildPanel(); // panel needs a builder method
frame.revalidate(); // in- and validate in one !!
frame.pack(); //
if you want to resize, you need preferredSize(); on panel or use repaint() if you don't need to resize frame.
Roman, the problem can be solved like that:
Do this in the beginning of your run method:
final JPanel partnerSelectionPanel = generatePartnerSelectionPanel();
Then do this
frame.getContentPane().add(partnerSelectionPanel);
Before you add the new panel do this:
partnerSelectionPanel.setVisible(false);
It works. I do not know if it is a safe and/or elegant solution but it works.
I'm in the process of creating a GUI in Netbeans 6.1 for my senior design project but i've run into an annoying snag. Temporary Windows like my login PopUp and others wont disappear when i tell it. I've been researching how to solve this for about 2 months on an off. I've even mad a separate thread for my Pop Up but it still wont work....the only way it will disappear if i literally dont mess with any of the other GUI components....my sample code should help describe my anger...dont mind the shadow code, it was for testing purposes, which obviously didnt help.
//This method is called once a user presses the "first" login button on the main GUI
public synchronized void loginPopUpThread() {
doHelloWorld = new Thread(){
#Override
public synchronized void run()
{
try
{
loginPopUpFrame.pack();
loginPopUpFrame.setVisible(true);
System.out.println("waitin");
doHelloWorld.wait();
System.out.println("Not Sleepin..");
loginPopUpFrame.pack();
loginPopUpFrame.setVisible(false);
}
catch (InterruptedException e)
{
}
}
};
doHelloWorld.start();
//This is called when the "second" loginB is pressed and the password is correct...
public synchronized void notifyPopUp() {
synchronized(doHelloWorld) {
doHelloWorld.notifyAll();
System.out.println("Notified");
}
}
I've also tried Swing Utilities but maybe i implemented it wrong as it's my first time using them. It essentially does the same thing as the code above except the window freezes when it gets to wait, which the above code doesnt do:
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public synchronized void run() {
try
{
loginPopUpFrame.pack();
loginPopUpFrame.setVisible(true);
System.out.println("waitin");
wait();
System.out.println("Not Sleepin.");
loginPopUpFrame.pack();
loginPopUpFrame.setVisible(false);
}
catch (InterruptedException e)
{
}
}
});
PLEASE HELP ME!!!
Rules of thumb:
Don't manipulate GUI components in arbitrary threads; always arrange to manipulate them in the event thread
Never wait or sleep inside the event thread (so, never inside code sent to invokeLater())
So the answer to how you solve this problem is "some other way"...
Standing back from the problem a bit, what is it you're actually trying to do? If you just want a login dialog to wait for the user to enter user name and password, is there a reason not to just use a modal JDialog (after all, that's what it's there for...).
If you really do want some arbitrary thread to wait for a signal to close the window/manipulate the GUI, then you need to do the waiting in the other thread, and then make that thread call SwingUtilities.invokeLater() with the actual GUI manipulation code.
P.S. There are actually some GUI manipulation methods that it is safe to call from other threads, e.g. calls that are "just setting a label" are often safe. But which calls are safe isn't terribly well-defined, so it's best just to avoid the issue in practice.
The Swing components should only be manipulated by the swing event dispatch thread.
class SwingUtilites has methods to submit tasks to the dispatch thread.
It is difficult to diagnose your problem. I'm not sure what you're trying to do with the wait methods, but I recommend leaving wait/notify alone.
This code has two frames - when you create a second frame, the first is hidden until you close it.
public class SwapFrames {
private JFrame frame;
private JFrame createMainFrame() {
JButton openOtherFrameButton = new JButton(
"Show other frame");
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container contentPane = frame.getContentPane();
contentPane.setLayout(new FlowLayout());
contentPane.add(openOtherFrameButton);
frame.pack();
openOtherFrameButton
.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
onClickOpenOtherFrame();
}
});
return frame;
}
private void onClickOpenOtherFrame() {
frame.setVisible(false);
JFrame otherFrame = new JFrame();
otherFrame
.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
otherFrame.setContentPane(new JLabel(
"Close this to make other frame reappear."));
otherFrame.pack();
otherFrame.setVisible(true);
otherFrame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosed(WindowEvent e) {
frame.setVisible(true);
}
});
}
public static void main(String[] args) {
JFrame frame = new SwapFrames().createMainFrame();
frame.setVisible(true);
}
}
Because I don't see any evidence of them in your code, I'm going to suggest you read up on using event listeners rather than trying to "wait" for code to finish.
It isn't entirely clear what you're trying to achieve, but you might be better off with a modal dialog:
public class DialogDemo {
public JFrame createApplicationFrame() {
JButton openDialogButton = new JButton("Open Dialog");
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container container = frame.getContentPane();
container.setLayout(new FlowLayout());
container.add(openDialogButton);
frame.pack();
openDialogButton
.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
onOpenDialog(frame);
}
});
return frame;
}
private void onOpenDialog(JFrame frame) {
JDialog dialog = createDialog(frame);
dialog.setVisible(true);
}
private JDialog createDialog(JFrame parent) {
JButton closeDialogButton = new JButton("Close");
boolean modal = true;
final JDialog dialog = new JDialog(parent, modal);
dialog
.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
Container container = dialog.getContentPane();
container.add(closeDialogButton);
dialog.pack();
dialog.setLocationRelativeTo(parent);
closeDialogButton
.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
dialog.setVisible(false);
}
});
return dialog;
}
public static void main(String[] args) {
new DialogDemo().createApplicationFrame().setVisible(
true);
}
}
How about doing simply:
//This method is called once a user presses the "first" login button on the main GUI
public void loginPopUpThread() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
loginPopUpFrame.pack();
loginPopUpFrame.setVisible(true);
}
};
}
//This is called when the "second" loginB is pressed and the password is correct...
public void notifyPopUp() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
loginPopUpFrame.setVisible(false);
}
};
}
What you really want to be using is a modal JDialog.
Note, bits of this are left out. It's your homework/project.
public void actionPerformed(ActionEvent e)
{
// User clicked the login button
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
LoginDialog ld = new LoginDialog();
// Will block
ld.setVisible(true);
}
});
}
public class LoginDialog extends JDialog
{
public LoginDialog()
{
super((Frame)null, "Login Dialog", true);
// create buttons/labels/components, add listeners, etc
}
public void actionPerformed(ActionEvent e)
{
// user probably clicked login
// valid their info
if(validUser)
{
// This will release the modality of the JDialog and free up the rest of the app
setVisible(false);
dispose();
}
else
{
// bad user ! scold them angrily, a frowny face will do
}
}
}