Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm creating a card game in Java and would like to portray the appearance of dealing. I have JLabels created and am making them visible by using .setVisible(true) and would like to put a delay between each card being visible.
I've tried using wait() and Thread.sleep() but neither worked. wait() gave me errors and Thread.sleep just paused the entire program, not just each appearance. (This code runs when a "Next" button is pressed so it is in the actionPerformed method)
Note: I am a beginner.. please keep it simple :)
else if(eventName.equals("Next"))
{
rules.setVisible(false);
next.setVisible(false);
inst.setVisible(false);
cardDeck.setVisible(true);
discard.setVisible(true);
tot.setVisible(true);
specialCards.setVisible(true);
// delay here
userCard1.setVisible(true);
// delay here
compCard1.setVisible(true);
// delay here
userCard2.setVisible(true);
// delay here
compCard2.setVisible(true);
// delay here
userCard3.setVisible(true);
// delay here
compCard3.setVisible(true);
}
Use Timers to have the labels being shown after some time.
You will see in the docs that using them is really straight forward.
You could also just insert code that pauses your app for a certain amount of time like Thread.sleep, but this would render your app entirely unresponsive as long as the app waits.
Simple example:
package testTimer;
import java.awt.Component;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
public class TimerTest extends JFrame {
// These labels will be shown after some delay
JLabel l1 = null;
JLabel l2 = null;
public TimerTest() {
Container cpane = getContentPane();
cpane.setLayout(new BoxLayout(cpane, BoxLayout.Y_AXIS));
JLabel l = new JLabel("Timer Test");
l.setAlignmentX(Component.CENTER_ALIGNMENT);
cpane.add(l);
l.setVisible(true);
l1 = new JLabel("1");
l2 = new JLabel("2");
cpane.add(l1);
l1.setVisible(false);
cpane.add(l2);
l2.setVisible(false);
// Now prepare two timers, one for each label
int delayForL1Millis = 1000;
Timer t1 = new Timer(delayForL1Millis, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
l1.setVisible(true);
}
});
t1.setRepeats(false);
int delayForL2Millis = 2000;
Timer t2 = new Timer(delayForL2Millis, new ActionListener() {
public void actionPerformed(ActionEvent evt) {
l2.setVisible(true);
};
});
t2.setRepeats(false);
// And start them
t1.start();
t1 = null;
t2.start();
t2 = null;
}
public static void main(String[] argv) {
TimerTest timertest = new TimerTest();
timertest.setVisible(true);
}
}
Related
I am trying to create a seven segment display that automatically moves using the timer with the use of the ActionListener and actionPerformed.
I thought that if I use the for, if statement it would automatically loop from 0 to 2 and set the Background color for each segment of the numbers. However, when I display it, it is stuck on just displaying zero and will not count up from there.
Can anyone help me on what I am doing wrong, that makes this stuck on zero?
Here is the programming I have now using JFrame.
import javax.swing.Timer;
public class SevenSegment extends JFrame {
Timer timer = new Timer(100, null);
public SevenSegment() {
timer.start();
timer.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < 3; i++) {
if(i == 0) {
lblNumberOne.setBackground(Color.red);
lblNumberTwo.setBackground(Color.red);
lblNumberThree.setBackground(Color.red);
lblNumberFour.setBackground(Color.red);
lblNumberFive.setBackground(Color.red);
lblNumberSix.setBackground(Color.red);
}
else if(i == 1) {
lblNumberTwo.setBackground(Color.red);
lblNumberThree.setBackground(Color.red);
}
else if(i == 2) {
lblNumberOne.setBackground(Color.red);
lblNumberTwo.setBackground(Color.red);
}
}
}
});
}
}
Here's about as simple a Swing GUI clock as you can make.
I did this so I could show you a general way to start all of your Swing GUIs. Oracle has a helpful tutorial, Creating a GUI With JFC/Swing, that will show you how to create all kinds of Swing GUIs.
We start all Swing GUIs with a call to the SwingUtilities invokeLater method. This method ensures that all Swing components are created and executed on the Event Dispatch Thread.
We always create a JPanel to put our Swing components on. The only Swing component that we add to a JFrame is a JPanel or a JScrollPane. This allows us to separate the creation of a JFrame from the rest of the view. The JFrame code is nearly identical for all Swing applications. The only difference is the JPanels you add to the JFrame.
The JFrame code must be called in a specific order. This is the order I use for my Swing applications.
The JPanel code is in a separate paragraph for general tidiness. I like to keep things separate so I can focus on one small part of the GUI at a time.
The updateClockLabel method exists because I need to execute the code one time when I'm creating the JPanel, and five times a second thereafter, to actually update the JLabel.
By the way, I didn't write all this code (all 64 lines) in one shot. I wrote a little, tested a lot. My code was not correct the first time I wrote it, and I don't just mean making typos.
Here's the complete runnable code.
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class SimpleClock implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new SimpleClock());
}
private JLabel clockLabel;
#Override
public void run() {
JFrame frame = new JFrame("Clock");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
Timer timer = new Timer(200, new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
updateClockLabel();
}
});
timer.start();
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new FlowLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 45, 5, 45));
clockLabel = new JLabel(" ");
clockLabel.setFont(panel.getFont().deriveFont(Font.BOLD, 72f));
updateClockLabel();
panel.add(clockLabel);
return panel;
}
public void updateClockLabel() {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("H:mm:ss a");
String timeDisplay = LocalTime.now().format(formatter);
clockLabel.setText(timeDisplay);
}
}
I've recently made a small puzzle game that deals with clicking certain areas. I also made a solver which activates the necessary areas to win. The problem that I am facing is that I would like to pause each time it activates an area to create a sort of "solving animation". My problem is represented here
package experiment;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class ExperimentHere extends JFrame implements ActionListener
{
private static final long serialVersionUID = 1L;
private JButton changeLabelButton;
private JPanel mainPanel;
private JLabel labelToChange;
public ExperimentHere() {
changeLabelButton = new JButton("Set the label");
changeLabelButton.addActionListener(this);
mainPanel = new JPanel();
labelToChange = new JLabel();
labelToChange.setText("This needs to be changed");
mainPanel.add(labelToChange);
mainPanel.add(changeLabelButton);
this.add(mainPanel);
setTitle("Timer Program");
setContentPane(mainPanel);
setPreferredSize(new Dimension(1000, 1000));
pack();
}
public void actionPerformed(ActionEvent e) {
if (e.getSource().equals(changeLabelButton)){
changeLabel();
}
}
public void changeLabel(){
for (int i = 0; i<5; i++){
labelToChange.setText(""+i);
// Pause for 200ms here
}
}
public static void main(String[] args){
ExperimentHere test = new ExperimentHere();
test.setVisible(true);
}
}
I have tried using Timers, but I'm not sure how to format it properly so that it only pauses each time the loop inside of changeLabel() is incremented, because the second paramter in Timer() asks for an ActionListener.
I've also tried using Thread.sleep() but it just freezes my program and then instantly solves it.
Ideally the changeLabel method would increment by 1, set the label to the new String, wait for 200ms, and then increment again.
I have tried using Timers, but I'm not sure how to format it properly so that it only pauses each time the loop inside of changeLabel() is incremented
When you use a Timer you don't use a loop. The point of a Timer is that you start the Timer and it keeps executing until you stop the Timer.
You also don't make methods, you make an Action to invoke whenever the Timer fires.
So you need an instance variable in your class that keeps track of the number of times the Timer has fired (lets call it "timerCounter"). Then you need to create an Action to invoke every time the Timer is fired.
So you create a couple of instance variables:
int timerCounter = 0;
Action action;
Then in the constructor of your class you create an Action something like:
action = new AbstractAction()
{
#Override
public void actionPerformed(ActionEvent e)
{
labelToChange.setText("" + timerCounter);
timerCounter++;
if (timerCounter > 5)
{
Timer timer = (Timer)e.getSource();
timer.stop();
}
}
}
So now in the ActionListenerof your button you can do something like:
timerCounter = 0;
Timer timer = new Timer(200, action);
timer.start();
This question already has answers here:
How could I add a simple delay in a Java Swing application?
(3 answers)
Closed 6 years ago.
i'm making a poker game for a uni assignment and i was wondering if there is any way to have a method that does as follows ( Note: very roughly written up code )
JTextArea textArea = new JTextArea();
public void printer(String s){
//I want to delay here, for 2 seconds each time i print to the jtextarea
textArea.append(s);
}
public void runGame(){
printer("Dealing cards...");
//I want to delay to add to an effect of the time it takes to actually deal the cards
pokerHand.setVisibility(true);
printer("What you like to do?");
//
//Code here containing running the game
//
printer("Daniel Negreanu folds");
//I want to have a delay here for the time it takes to make a decision.
printer("Phil Hellmuth folds");
Theres many many more instances i want to use this throughout my program, and just wondered if there is any way to do this.
Thanks in advance
EDIT: Not looking to use Thread.sleep() as it doesn't work well with gui.
EDIT2: I want the pokerHand.setVisibility(true), and other methods in my code to execute AFTER the delay, ( using a timer doesn't do this ).
Not looking to use Thread.sleep() as it doesn't work well with gui.
Good, use a Swing Timer instead
I want the pokerHand.setVisibility(true), and other methods in my code to execute AFTER the delay, ( using a timer doesn't do this ).
Yes it does, you're just not using it properly, but since you've not provided any actual code, I can't say "how" you're not using it properly, only from the sounds of it, you are.
Start by taking a look at How to use Swing Timers for more details
The following is very simple example, it uses a Timer to calculate and print the amount of time between the time you clicked the button.
The example updates the UI AFTER the Timer is started, but until the Timer completes, the calculation and result are not generated
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.time.Duration;
import java.time.LocalTime;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JTextArea ta;
private JButton btn;
private Timer timer;
private LocalTime startTime, endTime;
public TestPane() {
setLayout(new BorderLayout());
ta = new JTextArea(10, 20);
add(new JScrollPane(ta));
btn = new JButton("Click");
add(btn, BorderLayout.SOUTH);
timer = new Timer(2000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
endTime = LocalTime.now();
Duration duration = Duration.between(startTime, endTime);
ta.append("Ended # " + endTime + "\n");
ta.append("Took " + (duration.toMillis() / 1000) + " seconds\n");
}
});
timer.setRepeats(false);
ta.setEditable(false);
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
timer.start();
startTime = LocalTime.now();
btn.setEnabled(false);
ta.append("Start # " + startTime + "\n");
}
});
}
}
}
First, your code seems to be imperative ("ask user what to do", "game loop goes here") instead of event-driven ("when this happens, do that"). Read up on event-driven programming, which is used on all GUIs, sooner rather than later.
In event-driven code, there is no big difference between "user clicks a button" and "timeout expires" - both will cause events that your code can react to. So start by rewriting your code so that, once you press a button, the "next thing" happens. Then change it again so that once a timer expires, the same "next thing" happens.
Assuming that you have the following code:
// an ActionListener for both clicks and timer-expired events
private nextThingListener = new ActionListener() {
public void actionPerformed(ActionEvent ae) {
doNextThing();
}
};
// method that does the next thing
public void doNextThing() {
// change the UI in some way
// if using timers, may also start the next timer
}
You can now associate it to a button using:
// create a button and have it do the "next thing" when clicked
JButton jb = new JButton("do next thing");
jb.addActionListener(nextThingListener);
myInterface.add(jb); // <-- display it in the interface somehow
And you can associate it to a timer as:
// launch a timer that will ring the nextThingListener every 2 seconds
new Timer(2000, nextThingListener).start();
If you want to have the timer ring only once, you can use
// launch a timer that will ring the nextThingListener after 2 seconds
Timer t = new Timer(2000, nextThingListener);
t.setRepeats(false);
t.start();
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
What I want to do in my java program is, that when I press the button it displays text in textfield in intervals of time.
i.e I press the button then a jFrame pops up and there is a label which shows text like:
1st second:"1st"
then a time lag of say 1 sec
then 2nd thing: "2nd"
I am a newbie and I tried to Google this problem but I couldn't find a solution even after 3-4 hours
I tried a lot of things: sleep, try n catch...
Please write the answer very simplified.
Here is my code:
In the following code, when the button is pressed, the jFrame comes but has a white screen in it and when the sum ends, its screen turns grey and it shows the answer....
private void jButton5ActionPerformed(java.awt.event.ActionEvent evt) {
See.setVisible(true);//See is the JFrame
t007.setVisible(true);//Label in See
l2.setVisible(true);//TextField in See
int ran, g, d, col, ran2;
double y = 1000 * (Double.parseDouble(t2.getText()));
int x = (int) y;
d = 0;
double c = Math.pow(10, Integer.parseInt(t1.getText()));
col = Integer.parseInt(t3.getText());
for (g = 0; g < col;) {
ran = (int) (Math.random() * (c)); // Random Number Creation Starts
if (ran > (c / 10)) {
g = g + 1;
ran2 = ((int) (Math.random() * 10)) % 2;
if (ran2 == 1) {
ran = ran * (-1);
}
d = d + ran;
if (d < 0) {
ran = ran * (-1);
d = d + (2 * ran);
}
l2.setVisible(true);
t007.setText("" + ran);
System.out.println("" + ran);
jButton6.doClick();
//Pausing (Sleep)
try {
Thread.sleep(x);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
}
}
l2.setText("" + d);
}
Swing is a single threaded framework, that is, all interactions and modifications to the UI are expected to occur within the context of the Event Dispatching Thread.
The EDT is responsible for, amongst other things, processing repaint requests.
Anything that stops the EDT from running (like Thread.sleep and looping for a long time) will prevent it from processing the events, virtually "hanging" your application until it becomes unblocked...
Now, I tried to decipher what you program was trying to do...but failed, so instead...I made a pretty counter...
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TickOver {
public static void main(String[] args) {
new TickOver();
}
public TickOver() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private JTextField field;
private JButton button;
private int tick;
private Timer timer;
public TestPane() {
field = new JTextField(10);
field.setEditable(false);
button = new JButton("Start");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
button.setEnabled(false);
tick = 0;
timer.start();
}
});
timer = new Timer(1000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
field.setText(Integer.toString(++tick));
if (tick > 4) {
timer.stop();
button.setEnabled(true);
}
}
});
timer.setInitialDelay(0);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(field, gbc);
add(button, gbc);
}
}
}
Take a close look at Concurrency in Swing for more details...
You should never sleep in UI thread, as it make the UI lag. As if the process takes time to complete the UI will get stuck and user experience will get hurt.
Use other mechanisms such as a Timer or SwingWorker
Concurrency in Swing
It's very bad practice to sleep the user interface thread. (As this will cause the application to become unresponsive.) You ought to put all this code inside the Run() method of a Runnable instance:
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
// Your code here.
}
});
The problem is that you run your long running loop on the event dispatch thread. But this is the thread that must dispatch all events of the application like mouse or keyboard events but also repaint events that causes your user interface to get repainted every time it gets 'dirty'. That means, while your for-loop is running, the user interface is not repainted nor are any other events processed. Your UI freezes!
Your jButton5ActionPerformed method should return as soon as possible so that the event dispatch thread can process other events. Your long running operation should be run by a separate thread in the background.
A good starting point is the following tutorial about concurrency in Swing:
http://docs.oracle.com/javase/tutorial/uiswing/concurrency/
Maybe you can use the SwingWorker class to perform your background work:
http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html
below in the sample code which i wrote where the user gets an interface with 2 buttons. when the user click on start button the timer starts and when the end button is clicked the timer stops and the difference in time is displayed.
But the difference in time is not being output:(
can someone help mi.
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
public class Timer2 extends JFrame {
private JButton start;
private JButton end;
public Timer2() {
super("Test Timer");
setLayout(new FlowLayout());
start = new JButton("START");
add(start);
end = new JButton("END");
add(end);
ButtonHandler handler = new ButtonHandler();
start.addActionListener(handler);
end.addActionListener(handler);
}
private class ButtonHandler implements ActionListener {
public void actionPerformed(ActionEvent event) {
long s_time = 0;
long e_time = 0;
long diff = 0;
String name = ((JButton) event.getSource()).getText();
if (name.equals("start")) {
s_time = System.currentTimeMillis();
} else {
e_time = System.currentTimeMillis();
}
diff = (e_time - s_time) / 1000;
JOptionPane.showMessageDialog(null, diff);
}
}
public static void main(String[] args) {
Timer2 timer2 = new Timer2();
timer2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
timer2.setSize(200, 200);
timer2.setVisible(true);
}
}
You've given your buttons text in UPPER CASE but then are looking for lower case in your event handler.
You also are setting both s_time and e_time to 0 inside the actionPerformed() method which means they are set to 0 every time you click. These both need to be fields in the ButtonHandler class.
In addition, the way you have it written, the JOptionPane.showMessageDialog() will be fired when you click either button.
Edit: To solve the last problem, move your diff calculation and JOptionPane.showMessageDialog() call to inside the else block it follows; you only want it when the "end" button is pressed.
I'm assuming you want to display the result only when the user clicks "End". The way you've written it, the dialog will be displayed either way. To resolve this, move the JOptionPane.showMessageDialog(null, diff) inside the else block.
Another thing, as #Brian Roach so helpfully explains, computers are very case sensitive (e.g. "THUS" does not equal "thus"). So, make sure you're referring to the correct item.