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.
Related
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?
I have a Swing application where I wish to add some delay. I have a close button, which on clicking should display the JTextArea which displays "Closing database connections...." and then execute Database.databaseClose() method and System.exit(). I have tried using Thread.sleep() method as in the code below for the delay. When I execute the program, the screen freezes for 2 seconds and then closes without displaying the JTextArea. The close button and JTextArea is added to JFrame directly.
What I want is that on clicking the close button, the JTextArea should be displayed immediately and then the application should delay for 2 seconds before finally implementing the Database.databaseClose() method and exiting the program. The Database.databaseClose() method works just fine.
I am a beginner at Swings and would greatly appreciate it if anyone could modify the code to implement the requirement above. Thanks!
Here's the code snippet:
JButton btnClose = new JButton("Close");
btnClose.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
JTextArea txtrClosingDatabaseConnections = new JTextArea();
txtrClosingDatabaseConnections.setText("\r\n\tClosing database connections....");
getContentPane().add(txtrClosingDatabaseConnections);
validate();
repaint();
/*
try
{
Thread.sleep(2000);
}
catch (InterruptedException e2)
{
e2.printStackTrace();
}
*/
try
{
Database.databaseClose();
}
catch (Exception e1)
{
e1.printStackTrace();
}
System.exit(0);
}
});
getContentPane().add(btnClose);
Hej, this is an example method that initializes an JMenuBar on a JFrame in Swing.
private JMenuBar initMenuBar() {
JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("File");
exitApp = new JMenuItem("Exit App");
exitApp.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Timer t = new Timer(2000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
JOptionPane.showMessageDialog(getParent(), "Closing App in 2 Seconds");
t.start();
}
});
fileMenu.add(exitApp);
menuBar.add(fileMenu);
return menuBar;
}
May it will help you. It creates an JOptionPane, which must be closed by clicking OK, then the JFrame will be closed after 2 seconds.
Your code is executing on the Event Dispatch Thread, so you can't use a Thread.sleep() since that will block the EDT and prevent it from repainting the GUI.
You need to use a separate Thread for you database processing. Read the section from the Swing tutorial on Concurrency for more information as well as a solution that uses a SwingWorker to manager this Thread for you.
The Timer is the solution. The Swing timer's task is performed in the event dispatch thread. This means that the task can safely manipulate components, but it also means that the task should execute quickly.
You can use Swing timers in two ways:
To perform a task once, after a delay.
For example, the tool tip manager uses Swing timers to determine when to show a tool tip and when to hide it.
To perform a task repeatedly.
For example, you might perform animation or update a component that displays progress toward a goal.
Please go through http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html for more details.
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 have a game that runs off of JPanel which has on it many other things which have their own independent timers and such. It seems that when I try to remove the panel from my frame to replace it with another JPanel it refuses to actually end all of its own processes. So even if I am able to remove it from the screen of the panel by removing it and setting it null, its processes are still going off in the background, IE the music and the stuff flying around.
What i need to know is some solution as to how to completely kill this JPanel and terminate its life to its entirety.
Seems not many people have run into this problem.
I remember having that issue in my own game..
Simply create some custom method i.e destroy() which will stop all timers gameloops music etc.
i.e
MyPanel panel=new MyPanel();
...
panel.destory();//stop music, timers etc
frame.remove(panel);
//refresh frame to show changes
frame.revalidate();
frame.repaint();
where panel would be:
class MyPanel extends JPanel {
private Timer t1,t2...;
//this method will terminate the game i.e timers gameloop music etc
void destroy() {
t1.stop();
t2.stop();
}
}
Alternatively you could make your Swing Timers observers of sorts by making it check each time whether the panel is visible and if not it should stop executing. This would though now of course cause you to create a timer which will only start the others once the panel becomes visible:
class MyPanel extends JPanel {
private Timer t1,t2,startingTimer;
MyPanel() {
t1=new Timer(60,new AbstractAction() {
#Override
public void actionPerformed(ActionEvent ae) {
if(!MyPanel.this.isVisible()) {//if the panel is not visible
((Timer)(ae.getSource())).stop();
}
}
});
startingTimer=new Timer(100,new AbstractAction() {
#Override
public void actionPerformed(ActionEvent ae) {
if(MyPanel.this.isVisible()) {//if the panel is visible
t1.start();//start the timers
t2.start();
((Timer)(ae.getSource())).stop();//dont forget we must stop this timer now
}
}
});
startingTimer.start();//start the timer which will check when panel becomes visible and start the others as necessary
}
}
now all you would do is:
frame.remove(panel);//JPanel timers should also see panel is no more visible and timer will stop
//refresh frame to show changes
frame.revalidate();
frame.repaint();
Try this:
myFrame.getContentPane().remove(myPanel);
myFrame.validate();
Make sure your music and other components are within the panel so they are removed as well.
I am trying to move an label/icon & button from one place to another place using setLocation method but for some reason the objects are moving but not in motion. So if any one knows how to do this thing please tell me.
How to create a label or any component that moves from one place to another place in JFrame?
Below I have shown the code:
jl = JLabel
jf = JFrame
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==jbtn)
{
for(int i=0;i<=30;i++)
{
jl.setLocation(100,100+i);
jl.repaint();
jf.repaint();
try
{
Thread.sleep(50);
}
catch(Exception ae)
{
ae.printStackTrace();
}
}
}
}
Essentially you are blocking the thread (the Event Dispatching Thread) responsible for painting the updates
You might like to have a read of java timer change delay with button and Does displaying Java GUI requires some special treatment? which shows animation in swing and discusses the importance of the EDT.