For some awkward reason whenever I set my desired frame to Visible(true) inside of my actionPerformed() it prints out the frame, with the title but no components and no colours that I have previous selected.
However, when setting the visibility to true in the top of my current frame(Without having to press the button) it working fine.
This is the frame I'm using:
But this is being printed once I set visibility to true inside the actionPerformed:
I have already got another frame(The main client frame) being set to true inside the actionPerformed() and it works fine. This is the first time this issue happened to me so I'm really not sure what's causing it.
I also assumed that it may be due to the fact that during the actionPerformed the client has to connect to the particular server details but then again, the Frame object is being instantiated as soon as the first frame is instantiated so it should be just fine..
Here is my actionPerformed(), sorry for messy code:
JButton connectButton = new JButton("Connect");
connectButton.setBackground(SystemColor.activeCaption);
connectButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
//If any of the first three fields are empty, turn them red
if(serverField.getText().equalsIgnoreCase("")){
lblSever.setForeground(new Color(240, 128, 128));
}
if(channelField.getText().equalsIgnoreCase("")){
lblChannel.setForeground(new Color(240, 128, 128));
}
if(nicknameField.getText().equalsIgnoreCase("")){
lblNickname.setForeground(new Color(240, 128, 128));
}
//Set Waiting Connection frame to true
wc.setVisible(true);
//None of the first three fields are empty
if(!serverField.getText().equalsIgnoreCase("")
&& !channelField.getText().equalsIgnoreCase("")
&& !nicknameField.getText().equalsIgnoreCase("")){
//Set current frame visibility to false
setVisible(false);
//Set connection details
Main.bot.setServer(serverField.getText());
Main.bot.setChannel(channelField.getText());
Main.bot.setNickname(nicknameField.getText());
Main.bot.setPassword(formattedTextField.getText());
//Connect to server and channel
try{
Main.bot.connect(serverField.getText());
Main.bot.changeNick(nicknameField.getText());
Main.bot.joinChannel(channelField.getText());
}catch(Exception e){ //Catch all errors, if invalid server is thrown, close Waiting Connection frame
InvalidServer error = new InvalidServer();
e.printStackTrace();
wc.setVisible(false);
wc.dispose();
error.setVisible(true);
}
setVisible(false);
//Custom Timer class
Timer runTime = new Timer();
while(runTime.getTimeElapsed() < 5000){
//To-Do
}
wc.setVisible(false);
//Instantiate next frame
MainFrame mainFrame = new MainFrame();
mainFrame.setVisible(true);
//Kill current frame
dispose();
}
}
});
Some Points:
Call frame.setVisible(true) in the end after adding all the components.
Use Swing Timer that is most suitable for swing application for any delay.
Read more How to Use Swing Timers
Use SwingUtilities.invokeLater() or EventQueue.invokeLater() to make sure that EDT is initialized properly.
Read more
Why to use SwingUtilities.invokeLater in main method?
SwingUtilities.invokeLater
Should we use EventQueue.invokeLater for any GUI update in a Java desktop application?
Read more The Use of Multiple JFrames, Good/Bad Practice?
Related
The code snippet below sets text in a JLabel, which is added to a JPanel, which is attached to a JFrame. No matter what I do though (such as repaint(), revalidate(), etc) I cannot get the UI to update the text until the Action Listener is done.
I have never had this problem before, possible because I have never had to have several things happen in a single firing of Action Listener. What am I missing?
TL;DR Why does the following not update the text on the screen until it has finished firing the Action Listener, even if I put in repaint() after each listPanel.add()?
final JFrame guiFrame = new JFrame();
final JPanel listPanel = new JPanel();
listPanel.setVisible(true);
final JLabel listLbl = new JLabel("Welcome");
listPanel.add(listLbl);
startStopButton.addActionListener(new ActionListener(){#Override public void actionPerformed(ActionEvent event){
if(startStopButton.getText()=="Start"){
startStopButton.setVisible(false);
listPanel.remove(0);
JLabel listLbl2 = new JLabel("Could not contact”);
listPanel.add(listLbl2);
JLabel listLbl2 = new JLabel("Success”);
listPanel.add(listLbl2);
}
}
guiFrame.setResizable(false);
guiFrame.add(listPanel, BorderLayout.LINE_START);
guiFrame.add(startStopButton, BorderLayout.PAGE_END);
//make sure the JFrame is visible
guiFrame.setVisible(true);
EDIT:
I attempted to implement SwingWorker, but still the interface is not updating until the action interface finishes firing. Here is my SwingWorker code:
#Override
protected Integer doInBackground() throws Exception{
//Downloads and unzips the first video.
if(cameraBoolean==true)
panel.add(this.downloadRecording(camera, recording));
else
panel.add(new JLabel("Could not contact camera "+camera.getName()));
panel.repaint();
jframe.repaint();
return 1;
}
private JLabel downloadRecording(Camera camera, Recording recording){
//does a bunch of calculations and returns a jLabel, and works correctly
}
protected void done(){
try{
Date currentTime = new Timestamp(Calendar.getInstance().getTime().getTime());
JOptionPane.showMessageDialog(jframe, "Camera "+camera.getName()+" finished downloading at "+currentTime.getTime());
}catch (Exception e){
e.printStackTrace();
}
}
Basically, SwingWorker (as I implemented it) is not properly updating the JPanel and JFrame. If I try to do the repaint in the "done()", they are not updated either. What am I missing?
Additionally, as soon as the JOptionPane displays itself, no more panels can be added to my jframe. I am unsure what is causing that either.
The action listener is being executed on the Event Dispatch Thread. For tasks like that, consider using a SwingWorker.
This would allow you to process your logic without blocking the updates (and thus the repaints) of the JFrame.
At a high level, this is what I mean:
startStopButton.addActionListener(new ActionListener(){#Override public void actionPerformed(ActionEvent event){
if(startStopButton.getText()=="Start"){
// Start SwingWorker to perform whatever is supposed to happen here.
}
You can find some information on how to use SwingWorker here, should you need it.
I am having trouble moving this JLabel across this JPanel? I put the code below. Basically what is supposed to happen, is the JLabel called "guy" slowly moves to the right. The only problem is, that the JLabel isn't refreshing it just disappears after the first time I move it.
public class Window extends JFrame{
JPanel panel = new JPanel();
JLabel guy = new JLabel(new ImageIcon("guy.gif"));
int counterVariable = 1;
//Just the constructor that is called once to set up a frame.
Window(){
super("ThisIsAWindow");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(panel);
panel.setLayout(null);
}
//This method is called once and has a while loop to exectue what is inside.
//This is also where "counterVariable" starts at zero, then gradually
//goes up. The variable that goes up is suposed to move the JLabel "guy"...
public void drawWorld(){
while(true){
guy.setBounds(counterVariable,0,50,50);
panel.add(guy);
counterVarialbe++;
setVisible(true);
try{Thread.sleep(100)}catch(Exception e){}
}
}
Any thoughts as to why the JLabel is just disappearing instead of moving to the right after I change the variable "counterVariable".
-Thanks! :)
Your code is causing a long-running process to run on the Swing event thread which is preventing this thread from doing its necessary actions: paint the GUI and respond to user input. This will effectively put your entire GUI to sleep.
Issue & suggestions:
Never call Thread.sleep(...) on the Swing Event Dispatch Thread or EDT.
Never have a while (true) on the EDT.
Instead use a Swing Timer for all of this.
No need to keep adding the JLabel to the JPanel. Once added to the JPanel, it remains there.
Likewise, no need to keep calling setVisible(true) on the JLabel. Once visible, it remains visible.
Call repaint() on the container holding the moving JLabel after you've moved it to request that the container and its children be re-drawn.
e.g.,
public void drawWorld(){
guy.setBounds(counterVariable,0,50,50);
int timerDelay = 100;
new javax.swing.Timer(timerDelay, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
countVariable++;
guy.setBounds(counterVariable,0,50,50);
panel.repaint();
}
}).start;
}
caveat: code not compiled, run, or tested in any way
I am trying to display a Loading Image in a new JFrame when the User clicks a particular button in my application.The JFrame is displayed,but it shows nothing!,also with a WHITE background,whereas all the JFrames have a grey default background.What is Wrong here?
stop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
analyzer.running=false;
JFrame Load1=new JFrame("Load1");
ImageIcon icon1=new ImageIcon("./ajax-loader.gif");
System.out.println(icon1.getIconHeight());
Load1.add(new JLabel("Retrieving...", icon1, JLabel.CENTER),BorderLayout.CENTER);
Load1.pack();
Load1.setSize(400,400);
Load1.setVisible(true);
System.out.println("Start Processing");
parser.parse(); // Time Consuming method
nw_Creator.create();
System.out.println("End Processing");
Load1.setVisible(false);
home.setVisible(false);
screen2.setVisible(true);
}
});
Do not put time consuming parts in an event handler or any method running in the event dispatch thread. You may want to use a swing worker instead.
What is happening is that you are never releasing the UI thread, so your JFrame is never painted. Since all graphics operations are done on the UI thread, you must release it, do your calculations, then close the frame if you want the jframe to display anything.
I have a problem with my application where the user will open more than one window at a time. And i have added dispose() method to call on closing the window. Now i should keep at-least one window open all the time so that the application does not hides without closed fully. If you don't understand read the following scenario:
I have window A and window B opened at the same time. Now i can close either window A or Window B but not both. In other words window B should be allowed to close only if window A is opened and vice versa. How do i do this in swing ??
A simple kind-of windowManger is not really tricky, all you need is
WindowListener which keeps tracks of the Windows it's listening to
a defined place to create the windows and register the the listener
make the windows do-nothing-on-close and make the listener responsible for the decision of whether to close or not (will do so for all except the last)
Some snippet:
// the listener (aka: WindowManager)
WindowListener l = new WindowAdapter() {
List<Window> windows = new ArrayList<Window>();
#Override
public void windowOpened(WindowEvent e) {
windows.add(e.getWindow());
}
#Override
public void windowClosing(WindowEvent e) {
if (windows.size() > 1) {
windows.remove(e.getWindow());
e.getWindow().dispose();
}
}
};
// create the first frame
JFrame frame = createFrame(l);
frame.setVisible(true);
// a method to create a new window, config and add the listener
int counter = 0;
private JFrame createFrame(final WindowListener l) {
Action action = new AbstractAction("open new frame: " + counter) {
#Override
public void actionPerformed(ActionEvent e) {
JFrame frame = createFrame(l);
frame.setVisible(true);
}
};
JFrame frame = new JFrame("someFrame " + counter++);
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.add(new JButton(action));
frame.addWindowListener(l);
frame.pack();
frame.setLocation(counter * 20, counter * 10);
return frame;
}
Just a possible approach...
Create a class, call it WindowManager, that manages creation and disposal of windows.
It could for example retain the count of the windows currently open, and allow a dispose operation only if there are more than one windows "alive", otherwise show a confirm message with JOptionPane telling the user "Really close? That would terminate the application." or something like that.
The "tricky" part is that you have to do this kind of window-related operations throughout the WindowManager, otherwise everything would screw up.
Dunno if Swing has something like this built-in, I've never seen such a scenario.
simply check if the other window is open before closing with window.isVisible();
My program starts with a picture with a textfield in a JFrame. I want when the user types start it closes the picture JFrame and opens another JFrame with the main program. I've tried
processEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
on the Image frame but it closes all the windows.
The method JFrame.setVisible can be used to hide or display the JFrame based on the arguments, while JFrame.dispose will actually "destroy" the frame, by closing it and freeing up resources that it used. Here, you would call setVisible(false) on the picture frame if you intend to reopen it, or call dispose() on the picture frame if you will not be opening it again, so your program can free some memory. Then you would call setVisible(true) on the main frame to make it visible.
you also can use this code
for example
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
Maybe if you set the picture JFrame's default close operation to something besides EXIT_ON_CLOSE, perhaps DISPOSE_ON_CLOSE, you can prevent your application from closing before the second JFrame appears.
This post is a bit old but nevertheless.
If you initialize the form like that:
JFrame firstForm = new JFrame();
firstForm.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
firstForm.setSize(800, 600);
firstForm.setLocationRelativeTo(null);
firstForm.setVisible(true);
And for instance create or open another form by a button:
JFrame secondForm = new JFrame();
secondForm.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
secondForm.setSize(800, 600);
secondForm.setLocationRelativeTo(null);
secondForm.setVisible(true);
this.dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
This will dispose and destroy the first window without exiting the program.
The key is to set setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE).
It also raises the events (I've tested it with the WindowClosing event).
Here is my solution to this problem:
public void actionPerformed(ActionEvent e) {
String userName = textField.getText();
String password = textField_1.getText();
if(userName.equals("mgm") && password.equals("12345")) {
secondFrame nF = new secondFrame();
nF.setVisible(false);
dispose();
}
else
{
JOptionPane.showMessageDialog(null, " Wrong password ");
}
}
you also can use this :
opens_frame frameOld= new opens_frame();
frameOld.setVisible(true);
Closing_Frame.setVisible(false);
Closing_Frame.dispose();
private void closeTheCurrentFrameAndOpenNew(java.awt.event.ActionEvent evt){
dispose();//To close the current window
YourClassName closeCurrentWindow = new YourClassName();
closeCurrentWindow.setVisible(true);//Open the new window
}
I was searching for the same thing and found that using "this" is the best and easiest option.
you can Use the following code:
this.dispose();
For netbeans use the reference of the current Object and setVisible(false);
for example
private void submitActionPerformed(java.awt.event.ActionEvent evt)
{
// TODO add your handling code here:
this.setVisible(false);//Closing the Current frame
new login().setVisible(true);// Opening a new frame
}
First call it
new Window().nextjframe.setVisible(true);
thisjframe.setVisible(false);
if(username.equals("gaffar")&&password.equals("12345"))
{
label.setText("Be ready to continue");
//Start of 2nd jframe
NewJFrame1 n=new NewJFrame1();
n.setVisible(true);
//Stop code for ist jframe
NewJFrame m=new NewJFrame();
m.setVisible(false);
dispose();
}
This is what i came up for opening a new jframe while closing the other one:
JFrame CreateAccountGUI = new JFrame();
CreateAccountGUI.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
CreateAccountGUI.setSize(800, 600);
CreateAccountGUI.setLocationRelativeTo(null);
CreateAccountGUI.setVisible(true);
this.setVisible(false);