I'm quite new on JAVA, and i have a question (i hope my english is not too bad).
Here is my process :
Open a first JFrame in the Main, with a JButton (to open the second
JFrame).
On click, with ActionLister, i call the process to open my second
window, with a black background (this works very well).
BUT, if i add a long process (in my code, just a sleep(5000)) just after setVisible() my second JFrame, this one will appear in white, and waits for the sleep(5000) to end before being black.
Questions :
Can someone tell me why the second JFrames appears white until the
end of process ? Maybe i make something wrong when i build my JFrame
?
Can someone tell me how to show my second JFrame black BEFORE the process ends ?
I searched for a long time, and saw that if my second window is built direct in the main thread it's ok even with the sleep before end of process.
But when i am in another thread (like when i click on the button), that doesn't work good !
SECOND PART :
On click on the button from the first window :
The second window shows up (empty with black background). then, the result's calcul is launched.
Calculate the result cant take 20sec, and will find 1 element each 5 seconds.
Each times an element is found, i want it to be shown in the second window.
For that, i added an observer on this result from the JFrame, which will add an element each time one element is found. I hope you understand.
Here picture of what i want to make :
Process
Here my project .JAR : http://dl.free.fr/b5IUSStBJ
Here my result's calcul :
public void launchCalculateResult(){
String[] tabelements = {"test1","test2", "test3", "test4", "test5"};
for (int i=0; i < 5; i++){
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
_elementslist.add(tabelements[i]);
notifyObservers();
}
}
you can see that it adds an element in a list each 2 seconds, and then notify the observers (my second window), then the observer adds an element :
public void refresh(Observable o) {
_otherwindow.addResultElement(_result.getLastElement());
}
The behaviour I got :
The Result calculates good, and in the end the second window looks good, with its 5 elements. But during the result's search, my second windows remains empty and white . . .
I repeat the aim :
Each time an element is added in the Result, i want to show it in my second window.
You're calling the long process on the Swing event thread, and this will tie up the thread preventing it from doing its important jobs, including painting your new JFrame.
The canonical solution is to use a background thread for your long processes, and for Swing GUI's, you'd want to use a SwingWorker -- if the background process needs to communicate with the GUI (which is usually the case).
For the details on this problem and solution, please check out: Concurrency in Swing
Side issue: you'll usually not want to show multiple JFrames in your application. For why this is important and for how you can improve this design, please check out Multiple JFrames
For example
import java.awt.Color;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class SwingExample extends JPanel {
private JButton openDialogBtn = new JButton(new OpenDialogAction("Open Dialog"));
private JDialog dialog;
private DialogPanel dialogPanel = new DialogPanel();
public SwingExample() {
setPreferredSize(new Dimension(400, 400));
add(openDialogBtn);
}
private class OpenDialogAction extends AbstractAction {
public OpenDialogAction(String name) {
super(name);
}
#Override
public void actionPerformed(ActionEvent e) {
dialogPanel.setText("");
if (dialog == null) {
Window win = SwingUtilities.getWindowAncestor(SwingExample.this);
dialog = new JDialog(win, "Dialog", ModalityType.MODELESS);
dialog.add(dialogPanel);
dialog.pack();
dialog.setLocationRelativeTo(win);
}
new SwingWorker<Void, Integer> () {
private final int maxI = 5;
#Override
protected Void doInBackground() throws Exception {
for (int i = 0; i < maxI; i++) {
publish(i);
Thread.sleep(1000);
}
return null;
}
protected void process(java.util.List<Integer> chunks) {
for (Integer chunk : chunks) {
dialogPanel.setText("Time: " + chunk);
}
};
protected void done() {
dialogPanel.setText("Done!");
};
}.execute();
dialog.setVisible(true);
}
}
private class DialogPanel extends JPanel {
private JTextField textField = new JTextField(10);
public DialogPanel() {
setBackground(Color.BLACK);
setPreferredSize(new Dimension(200, 200));
add(textField);
}
public void setText(String text) {
textField.setText(text);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui() {
SwingExample mainPanel = new SwingExample();
JFrame frame = new JFrame("SwingExample");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}
Example 2: handles Strings being passed into a JList<String> using a SwingWorker<Void, String>
import java.awt.Color;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ActionEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class SwingExample extends JPanel {
private JButton openDialogBtn = new JButton(new OpenDialogAction("Open Dialog"));
private JDialog dialog;
private DialogPanel dialogPanel = new DialogPanel();
public SwingExample() {
setPreferredSize(new Dimension(400, 400));
add(openDialogBtn);
}
private class OpenDialogAction extends AbstractAction {
public OpenDialogAction(String name) {
super(name);
}
#Override
public void actionPerformed(ActionEvent e) {
dialogPanel.clearList();
if (dialog == null) {
Window win = SwingUtilities.getWindowAncestor(SwingExample.this);
dialog = new JDialog(win, "Dialog", ModalityType.MODELESS);
dialog.add(dialogPanel);
dialog.pack();
dialog.setLocationRelativeTo(win);
}
new SwingWorker<Void, String>() {
#Override
protected Void doInBackground() throws Exception {
String[] tabelements = { "test1", "test2", "test3", "test4", "test5" };
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
publish(tabelements[i]);
}
return null;
}
protected void process(java.util.List<String> chunks) {
for (String chunk : chunks) {
dialogPanel.addText(chunk);
}
};
protected void done() {
dialogPanel.addText("Done!");
};
}.execute();
dialog.setVisible(true);
}
}
private class DialogPanel extends JPanel {
private DefaultListModel<String> listModel = new DefaultListModel<>();
private JList<String> jList = new JList<>(listModel);
public DialogPanel() {
jList.setPrototypeCellValue("ABCDEFG HIJKLMNOP");
jList.setVisibleRowCount(6);
JScrollPane scrollPane = new JScrollPane(jList);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
setBackground(Color.BLACK);
setPreferredSize(new Dimension(200, 200));
add(scrollPane);
}
public void clearList() {
listModel.clear();
}
public void addText(String text) {
listModel.addElement(text);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui() {
SwingExample mainPanel = new SwingExample();
JFrame frame = new JFrame("SwingExample");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}
//Make constructor class for both JFrame then
//write this code into your JFrame where your button is accesing another JFrame
//Note:- jb=button var name,
// jf=JFrame vatr name,
// addnew()=JFrame Class to be open.
jb.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
new addnew();
jf.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
});
It might work as well.
Related
I have this code sample in a separate jDialog (jDialog is in the same package as that of JFrame) which used to check (using a Thread) if the jCheckBox1 in the jFrame is whether visible or not. JDialog is set to visible by clicking a JLabel (Change Password) in JFrame. I have not set the visibility of the JFrame even to false even after I click on the Change Password JLabel.
The problem I encountered is that even if the JFrame is not visible i.e when I run the JDialog separately (without clicking on the Change Password JLabel) it prints the "Visible" and I'm more than sure that the jFrame is not visible and not running.
This is the code snippet (Thread) I have used to check the visibility of the JFrame's jCheckBox1:
LockOptions lock = new LockOptions();
private void setLocation2() {
new Thread() {
public void run() {
boolean running = true;
while (running) {
try {
Thread.sleep(1000);
if (lock.jCheckBox1.isVisible()) {
System.out.println("Visible");
} else {
System.out.println("Not Visible");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
And this is the Code I have written in JFrame's Change Password JLabel:
private void jLabel9MouseClicked(java.awt.event.MouseEvent evt) {
Container c = new ChangePassword(this, rootPaneCheckingEnabled);
if (!c.isShowing()) {
c.setVisible(true);
hideMeToSystemTray();
this.requestFocusInWindow();
}
}
But when I run the JDialog separately (without clicking on the Change Password JLabel) it prints the "Visible"
I have attached a Screenshots of both JFrame and JDialog
JFrame containing jCheckBox1
JDialog:
OK, let's have the simplest possible example.
The following code creates a main frame having a button to create a new frame of class LockOptionsWindow, which extends JFrame.
The class FrameDemo implements Runnable. So can it be accessed on the event dispatching thread using SwingUtilities.invokeLater as mentioned in Swing's Threading Policy. So it is possible creating a new thread checklockoptionswindow which then can check whether the new window created by the button is visible or not visible.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class FrameDemo extends WindowAdapter implements ActionListener, Runnable {
private LockOptionsWindow lockoptionswindow;
private Thread checklockoptionswindow = new Thread();
private void showLockOptionsWindow() {
if (lockoptionswindow != null && lockoptionswindow.isDisplayable()) {
lockoptionswindow.setVisible(true);
lockoptionswindow.setExtendedState(Frame.NORMAL);
} else {
lockoptionswindow = new LockOptionsWindow();
lockoptionswindow.setSize(new Dimension(300, 100));
lockoptionswindow.setVisible(true);
lockoptionswindow.setExtendedState(Frame.NORMAL);
}
}
private void startCheckLockOptionsWindow() {
if (!checklockoptionswindow.isAlive()) {
checklockoptionswindow = new Thread() {
public void run() {
boolean running = true;
while (running) {
try {
Thread.sleep(1000);
if (lockoptionswindow.isVisible()) {
if (lockoptionswindow.getExtendedState() == Frame.ICONIFIED) {
System.out.println("Visible iconified");
} else {
System.out.print("Visible on screen ");
int x = lockoptionswindow.getLocation().x;
int y = lockoptionswindow.getLocation().y;
System.out.println("at position " + x + ", " + y);
}
} else {
System.out.println("Not Visible");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
checklockoptionswindow.start();
}
}
public void actionPerformed(ActionEvent e) {
showLockOptionsWindow();
startCheckLockOptionsWindow();
}
public void run() {
JFrame frame = new JFrame("FrameDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button = new JButton("Show LockOptions frame");
button.addActionListener(this);
Container contentPane = frame.getContentPane();
contentPane.add(button);
frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new FrameDemo());
}
class LockOptionsWindow extends JFrame {
public LockOptionsWindow() {
super("LockOptions frame");
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
}
}
}
Edited to determine whether the LockOptionsWindow is visible iconified only or is really showed as window on the screen.
I am slightly confused, I have a jFrame of which I have made in Netbeans. This jFrame has a jLabel, of which is set to setVisible(false); from the beginning. Whenever a specific method is called, I then set the jLabel to setVisible(true); and then use a timer to set it to false again after 2 seconds. Apparently it won't work and I am unable to figure out why. I am aware of the repaint(); method, but can figure out how to make that work either.
I know the actual method for setting the visibility is called, as I have set it to print a line with the current state, which it does.
My actual code is the one below.
public JFram() {
initComponents();
setResizable(false);
jLabel2.setVisible(false);
}
static void tesMethod() {
try {
//function that does something
} finally {
new JFram().showHide(); //call function which is supposed to change the vissibility of jLabel
}
}
void showHide() {
jLabel2.setVisible(true);
System.out.println("reached show");
new java.util.Timer().schedule(
new java.util.TimerTask() {
#Override
public void run() {
jLabel2.setVisible(false);
System.out.println("reached timer");
}
},
2000
);
}
The code below here is how I tried to use the repaint(); method.
void showHide() {
jLabel2.setVisible(true);
jLabel2.repaint();
System.out.println("reached show");
new java.util.Timer().schedule(
new java.util.TimerTask() {
#Override
public void run() {
jLabel2.setVisible(false);
jLabel2.repaint();
System.out.println("reached timer");
}
},
2000
);
}
I think your problem lies mainly in you using a java.util.Timer instead of a javax.swing.Timer and probably you're blocking the Event Dispatch Thread (EDT).
You could try this code and compare it with yours, I also don't see where you're adding your JLabel to your frame.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class ShyLabel {
private JFrame frame;
private JLabel label;
private Timer timer;
private boolean isVisible;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new ShyLabel().createAndShowGui();
}
});
}
public void createAndShowGui() {
String labelText = "I'm a shy label that hides every 2 seconds";
isVisible = true;
frame = new JFrame(getClass().getSimpleName());
label = new JLabel(labelText);
timer = new Timer(2000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
label.setText(isVisible ? "" : labelText);
isVisible = !isVisible;
}
});
timer.setInitialDelay(2000);
timer.start();
frame.add(label);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
The below image is produced by the above code, however because of the time I recorded the GIF it looks really fast instead of taking 2 seconds as it should be...
May be it is a problem of layout.
As you set resizable to false before any layout calculation occurred, the label was ignored (as invisible) by the time of the first layout.
You could try revalidate().
It has been a while since the last time I did Swing programming, and today I'm getting back to it. I have a simple JList which is backed by DefaultListModel. I also have a JButton which will show a JFileChooser. When a directory is selected, the JList is supposed to be populated with the file names under the selected directory.
What I found is that occasionally (actually it happens randomly quite often), the list wont be updated until I click on the (seemingly blank) list. I thought by using DefaultListModel, I can just call addElement() which will trigger the fireIntervalAdded (which should repaint the list, the container, etc) ? ALso, I believe the actionPerformed() method is invoked inside the EDT, so I should just be able to update the DefaultListModel. Anyway.... I have also tried calling revalidate() and repaint() on the list, the container, etc without any success either.
Secondly, when the list already has some items in it, clicking the button (which triggers the filechooser to be shown) will clear up the JList entries (without calling clear() on the model).
The source code is available at:
https://github.com/alexwibowo/spider
Here is an abstract of the code (hopefully it is sufficient)
package org.github.alexwibowo.spider.gui;
import com.jgoodies.forms.factories.CC;
import com.jgoodies.forms.layout.FormLayout;
import javax.swing.*;
public class MainPanel extends JPanel {
public MainPanel() {
initComponents();
}
private void initComponents() {
toolBar1 = new JToolBar();
openFolderButton = new JButton();
splitPane1 = new JSplitPane();
scrollPane1 = new JScrollPane();
fileList = new JList();
//======== this ========
setLayout(new FormLayout(
"default:grow",
"default, $lgap, fill:default:grow"));
//======== toolBar1 ========
{
toolBar1.setFloatable(false);
//---- openFolderButton ----
openFolderButton.setIcon(UIManager.getIcon("Tree.openIcon"));
openFolderButton.setBorder(new EmptyBorder(5, 5, 5, 5));
toolBar1.add(openFolderButton);
}
add(toolBar1, CC.xy(1, 1));
//======== splitPane1 ========
{
//======== scrollPane1 ========
{
//---- fileList ----
fileList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
scrollPane1.setViewportView(fileList);
}
splitPane1.setLeftComponent(scrollPane1);
}
add(splitPane1, CC.xy(1, 3));
}
protected JToolBar toolBar1;
protected JButton openFolderButton;
protected JSplitPane splitPane1;
protected JScrollPane scrollPane1;
protected JList fileList;
}
and the panel which extends the above. This is the class which handles the addition of filenames to the list :
package org.github.alexwibowo.spider.gui
import javax.swing.*
import java.awt.event.ActionEvent
import java.awt.event.ActionListener
class BarcodeMainPanel extends MainPanel {
private DefaultListModel<String> listModel = new DefaultListModel<String>()
BarcodeMainPanel() {
initModels()
initEventHandling()
}
protected void initModels() {
fileList.model = listModel
}
protected void initEventHandling() {
openFolderButton.addActionListener(new ActionListener() {
#Override
void actionPerformed(ActionEvent e) {
JFileChooser chooser = new JFileChooser();
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
chooser.setLocation(50, 50);
if (chooser.showOpenDialog(BarcodeSpiderMainFrame.instance()) == JFileChooser.APPROVE_OPTION) {
listModel.clear()
File selectedDirectory = chooser.getSelectedFile()
selectedDirectory.eachFile {
listModel.addElement(it.name)
}
} else {
System.out.println("No Selection ");
}
}
})
}
}
The frame which contains the panel (just for completeness) :
package org.github.alexwibowo.spider.gui
import groovy.transform.Synchronized
import javax.swing.*
import java.awt.*
class BarcodeSpiderMainFrame extends JFrame{
private static BarcodeSpiderMainFrame INSTANCE;
BarcodeSpiderMainFrame(String title) throws HeadlessException {
super(title)
}
#Synchronized
public static BarcodeSpiderMainFrame instance() {
if (INSTANCE == null) {
INSTANCE = new BarcodeSpiderMainFrame("Spider")
INSTANCE.minimumSize = new Dimension(800,600)
INSTANCE.maximumSize = new Dimension(1024,768)
INSTANCE.defaultCloseOperation = EXIT_ON_CLOSE
}
INSTANCE.initializeContent()
INSTANCE.visible = true
INSTANCE
}
private void initializeContent() {
BarcodeMainPanel mainPanel = new BarcodeMainPanel()
this.contentPane.add(mainPanel);
}
}
and finally the launcher (just for completeness) :
package org.github.alexwibowo.spider
import org.github.alexwibowo.spider.gui.BarcodeSpiderMainFrame
import javax.swing.*
#Singleton
class SpiderLauncher {
BarcodeSpiderMainFrame barcodeSpiderMainFrame
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
SpiderLauncher.instance.run(args);
}
});
}
void run(String[] args) {
barcodeSpiderMainFrame = BarcodeSpiderMainFrame.instance()
barcodeSpiderMainFrame.show()
}
}
This is what fixes it.
In BarcodeSpiderMainFrame, remove the call to setVisible. So it will look something like:
public static BarcodeSpiderMainFrame instance() {
if (INSTANCE == null) {
INSTANCE = new BarcodeSpiderMainFrame("Spider")
INSTANCE.minimumSize = new Dimension(800,600)
INSTANCE.preferredSize = new Dimension(1024,768)
INSTANCE.maximumSize = new Dimension(1024,768)
INSTANCE.defaultCloseOperation = EXIT_ON_CLOSE
}
INSTANCE.initializeContent()
// INSTANCE.visible = true // remove this line
INSTANCE
}
and in the launcher, call setVisible()
#Singleton
class SpiderLauncher {
BarcodeSpiderMainFrame barcodeSpiderMainFrame
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
SpiderLauncher.instance.run(args);
}
});
}
void run(String[] args) {
barcodeSpiderMainFrame = BarcodeSpiderMainFrame.instance()
barcodeSpiderMainFrame.pack()
barcodeSpiderMainFrame.setVisible(true) // add this line
}
}
I have added the call to pack(). But i dont think it really matters. How did the above fix my problem? I do not know. It would be great if someone can explain what actually happened.
I have a function graphics() that creates my JFrame and two JRadioButtons and adds ActionListeners to them. This graphics is called from main() and graphics itself calls game().
public void game() throws Exception
{
jTextArea1.setLineWrap(true);
jTextArea1.setWrapStyleWord(true);
jTextArea1.setText("This is private information.");
jRadioButton1.setVisible(true);
jRadioButton2.setVisible(true);
try {
t.sleep(40000);
repaint();
} catch (InterruptedException e) {
// We've been interrupted: no more messages.
return;
}
After displaying "This is private information." in the text Area, I want the program execution to pause for 40 seconds, or until the user presses the JRadioButton, whichever is earlier. So I added an ActionListener and called t.interrupt() inside it.
private void jRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {
t.interrupt();
jRadioButton1.setVisible(false);
jRadioButton2.setVisible(false);
//System.out.println(t.interrupted());
jTextArea1.setText("Please wait...");
}
However, even after choosing the JRadioButton which should trigger the interrupt, that does not happen and t.interrupted returns false.
Any help would be appreciated.
Never, ever call Thread.sleep(...) on the Swing event thread as you will freeze the thread and effectively freeze your program. The solution is to consider use of a Swing Timer for the time-dependent portion of your requirement and using a SelectionListener for the JCheckBox or JRadioButton requirement.
For example:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.*;
public class PausingExecution extends JPanel {
private static final String SELECTED_TEXT = "Snafus are Better!!!";
private static final String UNSELECTED_TEXT = "Fubars Rule!!";
private static final String TIMES_UP = "Time's Up!!!!";
private static final int TIMER_DELAY = 10 * 1000;
private JTextField messageField = new JTextField(UNSELECTED_TEXT, 10);
private JCheckBox checkBox = new JCheckBox("Click Me");
public PausingExecution() {
add(messageField);
add(checkBox);
checkBox.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent iEvt) {
if (iEvt.getStateChange() == ItemEvent.SELECTED) {
messageField.setText(SELECTED_TEXT);
} else {
messageField.setText(UNSELECTED_TEXT);
}
}
});
Timer mySwingTimer = new Timer(TIMER_DELAY, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
messageField.setText(TIMES_UP);
checkBox.setEnabled(false);
}
});
mySwingTimer.setRepeats(false);
mySwingTimer.start();
}
private static void createAndShowGui() {
PausingExecution mainPanel = new PausingExecution();
JFrame frame = new JFrame("PausingExecution");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
I've got a "status" JLabel in one class (named Welcome) and the timer in another one (named Timer). Right now, the first one displays the word "status" and the second one should be doing the countdown. The way I would like it to be, but don't know how to - display 10, 9, 8, 7 ... 0 (and go to the next window then). My attempts so far:
// class Welcome
setLayout(new BorderLayout());
JPanel area = new JPanel();
JLabel status = new JLabel("status");
area.setBackground(Color.darkGray);
Font font2 = new Font("SansSerif", Font.BOLD, 25);
status.setFont(font2);
status.setForeground(Color.green);
area.add(status, BorderLayout.EAST); // can I put it in the bottom-right corner?
this.add(area);
and the timer:
public class Timer implements Runnable {
// public void runThread() {
// new Thread(this).start();
// }
public void setText(final String text) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
setText(text); // link to status here I guess
}
});
}
public void run() {
for (int i = 10; i > 0; i--) {
// set the label
final String text = "(" + i + ") seconds left";
setText(text);
// // sleep for 1 second
// try {
// Thread.currentThread();
// Thread.sleep(1000);
// } catch (Exception ex) {
// }
}
// go to the next window
UsedBefore window2 = new UsedBefore();
window2.setVisible(true);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
// runThread();
}
} // end class
I agree that you should consider using a "Java" Timer as per Anh Pham, but in actuality, there are several Timer classes available, and for your purposes a Swing Timer not a java.util.Timer as suggested by Anh would suit your purposes best.
As for your problem, it's really nothing more than a simple problem of references. Give the class with the label a public method, say setCountDownLabelText(String text), and then call that method from the class that holds the timer. You'll need to have a reference of the GUI class with the timer JLabel in the other class.
For example:
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class Welcome extends JPanel {
private static final String INTRO = "intro";
private static final String USED_BEFORE = "used before";
private CardLayout cardLayout = new CardLayout();
private JLabel countDownLabel = new JLabel("", SwingConstants.CENTER);
public Welcome() {
JPanel introSouthPanel = new JPanel();
introSouthPanel.add(new JLabel("Status:"));
introSouthPanel.add(countDownLabel);
JPanel introPanel = new JPanel();
introPanel.setPreferredSize(new Dimension(400, 300));
introPanel.setLayout(new BorderLayout());
introPanel.add(new JLabel("WELCOME", SwingConstants.CENTER), BorderLayout.CENTER);
introPanel.add(introSouthPanel, BorderLayout.SOUTH);
JPanel usedBeforePanel = new JPanel(new BorderLayout());
usedBeforePanel.setBackground(Color.pink);
usedBeforePanel.add(new JLabel("Used Before", SwingConstants.CENTER));
setLayout(cardLayout);
add(introPanel, INTRO);
add(usedBeforePanel, USED_BEFORE);
new HurdlerTimer(this).start();
}
private static void createAndShowUI() {
JFrame frame = new JFrame("Welcome");
frame.getContentPane().add(new Welcome());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
public void setCountDownLabelText(String text) {
countDownLabel.setText(text);
}
public void showNextPanel() {
cardLayout.next(this);
}
}
class HurdlerTimer {
private static final int TIMER_PERIOD = 1000;
protected static final int MAX_COUNT = 10;
private Welcome welcome; // holds a reference to the Welcome class
private int count;
public HurdlerTimer(Welcome welcome) {
this.welcome = welcome; // initializes the reference to the Welcome class.
String text = "(" + (MAX_COUNT - count) + ") seconds left";
welcome.setCountDownLabelText(text);
}
public void start() {
new Timer(TIMER_PERIOD, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (count < MAX_COUNT) {
count++;
String text = "(" + (MAX_COUNT - count) + ") seconds left";
welcome.setCountDownLabelText(text); // uses the reference to Welcome
} else {
((Timer) e.getSource()).stop();
welcome.showNextPanel();
}
}
}).start();
}
}
Since you're using Swing you should use the javax.swing.Timer, not the java.util.Timer. You can set the timer to fire at 1 second (1000 ms) intervals and have your listener do the updating. Since Swing updates must take place in the event dispatch thread your listener is the perfect place for status.setText.
there's already a Timer class in java: http://www.exampledepot.com/egs/java.util/ScheduleRepeat.html
Why not put the setText method in the welcome class and just do 'status.setText(text)'?
And you might try BorderLayout.SOUTH or .PAGE END or .LINE END to get the timer in the lower right corner