Please help, I'm trying to use javax.swing.Timer in my program. I have looked at lots of examples, but it still doesn't make sense to me. I am writing a program that has the user guessing the price. What I can't seem to figure out is how to have a timer that counts down from 30 seconds after the "new Game" button is clicked. If the user has not guessed the correct answer, then I want the game to display "You lose", but I also want the timer to stop if they get the correct answer in under 30 seconds and display that time. I believe I'm suppose to use
timer = new Timer(Speed, this);
timer.start();
timer.end();
but, I'm not sure what else I need for the timer or where to place these within my code. Any help would be much appreciated. Below is the code for my program...
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;
public class ClockGame extends JFrame {
//Declare fields for GUI components
private JTextField guessField;
private JButton newGameButton;
private JLabel messageLabel;
private JLabel guessLabel;
private ImageIcon clockImage;
private int countTotal;
private Random rand;
private JLabel title;
private int number;
private Timer timer;
public ClockGame() {
//Build GUI
super ("Clock Game");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Set layout
this.setLayout(new BorderLayout());
//Create the main panel
JPanel mainPanel = new JPanel();
//Create components and place them in the panel
rand = new Random();
guessLabel = new JLabel("Guess: ");
guessField = new JTextField(20);
messageLabel = new JLabel(" Click New Game to Begin");
clockImage = new ImageIcon("clock.jpg");
newGameButton = new JButton("New Game");
title = new JLabel("The Clock Game", clockImage, SwingConstants.CENTER);
//Set font for clockGameLabel
title.setFont(new Font("Calibri", Font.BOLD, 24));
//Set messageLabel Color
messageLabel.setOpaque(true);
messageLabel.setBackground(Color.yellow);
newGameButton.addActionListener(new ButtonListener());
guessField.addActionListener(new AnswerListener());
//Add components to the panel
mainPanel.add(guessLabel);
mainPanel.add(guessField);
mainPanel.add(newGameButton);
this.add(title, BorderLayout.NORTH);
this.add(messageLabel, BorderLayout.SOUTH);
//Add the panel to this JFrame
this.add(mainPanel, BorderLayout.CENTER);
//Sizes this JFrame so that it is just big enough to hold the components
this.setSize(340,225);
//Make the JFrame visible on the screen
this.setVisible(true);
}
private class AnswerListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
//Code to check to see if answer is correct
int sum = number;
int answer = Integer.parseInt(guessField.getText());
Color purple = new Color(153, 153, 253);
countTotal++;
if (sum < answer)
{
messageLabel.setText("Too High");
messageLabel.setBackground(Color.red);
}
else if (sum > answer)
{
messageLabel.setText("Too Low");
messageLabel.setBackground(purple);
}
else
{
messageLabel.setText("Correct! It took you " + countTotal + " tries, in " +
timer + " seconds");
messageLabel.setBackground(Color.yellow);
}
}
}
private class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
number = rand.nextInt(1001);
messageLabel.setText(" The price is between $1 and $1000, begin.");
messageLabel.setBackground(Color.green);
countTotal = 0;
}
}
public static void main(String[] args) {
ClockGame frame = new ClockGame();
}
}
timer.end();
There is no end() method. First you need to read the API for the appropriate method to use.
counts down from 30 seconds after the "new Game" button is clicked.
So in the ActionListener you add to the button you need to start the Timer and schedule it to fire every second. When the Timer fires you decrement your count by 1.
I also want the timer to stop if they get the correct answer
So when they get the correct answer you stop the Timer. So in your code where you update the text of the label you stop the Timer.
If the user has not guessed the correct answer, then I want the game to display "You lose",
So when the timer count reaches 0, you 1) stop the timer and 2) display the message.
In the constructor of you class you would actually create the Timer, so that the above methods in your class have a reference to the Timer so it can be started and stopped as required.
What you really need to do is forget about your game and learn how to use a Timer. So you create a frame with a label and two buttons. The label will display the initial count of 30. Then you have a "Start" button that decrements the label by 1 each time the Timer fires. Then you have a "Stop" button that stops the Timer so the count is not decremented.
Once you understand the basic concept of starting and stopping the Timer, then you add the code to your real program.
Well to begin... you would need a JLabel that is assigned to print "You lose" and another one that prints the Time that it took the player to answer the question. Add these to your Frame however you want.
JLabel outcome = new JLabel(); //setText to win or lose.
JLabel countdown = new JLabel(); //setTime as Timer counts down.
After you have instantiated these Labels. The Timer needs to be instantiated.
Timer timer = new Timer(1000, new ActionListener() { //Change parameters to your needs.
int count = 30;
public void actionPerformed(ActionEvent e) {
count--;
if(count == 0) //They lose
{
countdown.setText("CountDown: " + count);
outcome.setText("You Lose");
timer.stop(); //ends the countdown.
}
else if(userGotAnswer) // You need to create a boolean value that changes when a user gets the answer right.
{
countdown.setText("CountDown: " + count);
outcome.setText("You win");
timer.stop(); //ends the countdown
}
else
{
countdown.setText("CountDown: " + count); //default
}
}
});
Then call
timer.start();
when you want the timer to start.
Related
This program is supposed to count mouse clicks but it only counts the first one. The code is nothing complicated but I don't get why it only counts the first click.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class swing {
private JLabel label;
public swing() {
JFrame frame = new JFrame("exemple");
frame.setBounds(200, 200, 200, 200);
JButton button = new JButton("clic clic");
button.addActionListener(new MyActionListener());
label = new JLabel("0");
JPanel pane = new JPanel();
pane.add(button);
pane.add(label);
frame.getContentPane().add(pane,
BorderLayout.CENTER);
frame.show();
}
private class MyActionListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
int count = 0;
count++;
label.setText("Number of Mouse Clicks = "+ count);
}
}
public static void main(String[] args) {
new swing();
}
}
Thank you to user WJS who has commented with an answer, I had to simply Move count =0 outside the actionPerformed method but inside the listener class.
on every click you are setting the counter again to zero and then showing the incremented value and after each click value of counter is reset to zero.
you need to move the count outside of actionPerformed
int count = 0;
private class MyActionListener implements ActionListener {
public void actionPerformed(ActionEvent event) {
count++;
label.setText("Number of Mouse Clicks = " + count);
}
}
So I have a radio button and after that I have an if/else statement that is based upon the outcome. But the if/else statements are supposed print things to the console, but they don't. Is something wrong with the Radio Buttons?
If you could, please provide thorough answers, as I'm not very good with Java. Thanks a ton :D
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class RadioButton extends JPanel {
int xDisplacement = 8;
int xVAvg = 8;
int xTime = 8;
static JFrame frame;
JLabel pic;
RadioListener myListener = null;
protected JRadioButton displacement;
protected JRadioButton vAvg;
protected JRadioButton time;
public RadioButton() {
// Create the radio buttons
displacement = new JRadioButton("Displacement");
displacement.setMnemonic(KeyEvent.VK_N);
displacement.setActionCommand("displacement")
//Displacement Button, set to automatically be clicked
vAvg = new JRadioButton("Average Velocity");
vAvg.setMnemonic(KeyEvent.VK_A);
vAvg.setActionCommand("averagevelocity");
//Acceleration Button
time = new JRadioButton("Change in time");
time.setMnemonic(KeyEvent.VK_S);
time.setActionCommand("deltaT");
//The change in time button
// Creates the group of buttons
ButtonGroup group = new ButtonGroup();
group.add(displacement);
group.add(vAvg);
group.add(time);
myListener = new RadioListener();
displacement.addActionListener(myListener);
vAvg.addActionListener(myListener);
time.addActionListener(myListener);
// Set up the picture label
pic = new JLabel(new ImageIcon(""+"numbers" + ".jpg")); //Set the Default Image
pic.setPreferredSize(new Dimension(177, 122));
// Puts the radio buttons down
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(0, 1));
panel.add(displacement);
panel.add(vAvg);
panel.add(time);
setLayout(new BorderLayout());
add(panel, BorderLayout.WEST);
add(pic, BorderLayout.CENTER);
setBorder(BorderFactory.createEmptyBorder(40,40,40,40));
}
//Listening to the buttons
class RadioListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
pic.setIcon(new ImageIcon(""+e.getActionCommand() + ".jpg"));
}
}
public static void main(String s[]) {
frame = new JFrame("∆x = Vavg * time");
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.exit(0);}
});
frame.getContentPane().add(new RadioButton(), BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
public void running() {
if ( displacement.isSelected()) {
//Option 1
System.out.println("The distance traveled on the x axis in meters is " + xDisplacement);
System.out.println("You can find the Average Velocity by dividing this number by time or find the time by dividing this number by the Average Velocity");
}
if ( vAvg.isSelected()) {
//Option 2
System.out.println("The average velocity in Meters per Second is " + xVAvg);
System.out.println("You can find the displacement by multiplying the time and this number together or to find the time, just divide the displacement by this number");
}
else {
//Option 3
System.out.println("The time in seconds is " + xTime);
System.out.println("You can find the displacement by multiplying the velocity times this number or you can find the average velocity by dividing the displacement by this number");
}
}
}
you are missing ; at this line of your code
displacement.setActionCommand("displacement")
and as MadProgrammer said call your running method in RadioListner class that implements ActionListner
class RadioListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
pic.setIcon(new ImageIcon(""+e.getActionCommand() + ".jpg"));
running();
}
}
Call running from your RadioListener's actionPerformed method
First of all hi! This is my first post on stackoverflow! This is my second attempt to program something in Java and the first ever attempt with a gui.
I'm actually having 2 problems. The first being the program and the second understanding a part of the code.
How the program should work:
When pressing start it counts down from 01:00 to 00:00 every minute (01:00 -> 00:59 -> 00:58). When you press stop, it stops counting down (duh) and when you press start again, it starts from 01:00 like the first time.
The program problem:
With that said. This only works the first time I press start. When I press start multiple times it subtracts that amount of times from the clock. Pressed 2 times (01:00 -> 00:58 -> 00:56). Pressed 4 times (01:00 -> 00:56 -> 00:52). etc... This obviously should not be happening.
The understanding problem:
I am having a hard time understanding why the timer requires an ActionListener and why it works when you use 'null'. In some cases it also works when using 'this' (which I also don't understand.).
Java Swing Timer Documentation
import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class CountdownClock extends JFrame
{
private int oneSecond = 1000; //Milliseconds
private Timer timer = new Timer(oneSecond * 60, null);
private int timerCount = 59;
public static void main(String args[])
{
new CountdownClock();
}
CountdownClock()
{
this.getContentPane().setLayout(null);
this.setBounds(800, 450, 300, 125);
final JLabel countdownLabel = new JLabel("01:00");
countdownLabel.setBounds(110, 10, 125, 30);
countdownLabel.setFont(new Font("Serif", Font.PLAIN, 30));
JButton startButton = new JButton("Start");
startButton.setBounds(10, 50, 125, 30);
startButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
timer.setRepeats(true);
timer.stop();
countdownLabel.setText("01:00");
timerCount = 59;
timer.start();
timer.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent evt)
{
if (timerCount == 0)
{
timer.stop();
countdownLabel.setText("00:00");
timerCount = 59;
}
else if (timerCount <= 9)
{
countdownLabel.setText("00:0" + String.valueOf(timerCount));
timerCount = timerCount - 1;
}
else
{
countdownLabel.setText("00:" + String.valueOf(timerCount));
timerCount = timerCount - 1;
}
}
});
}
});
JButton stopButton = new JButton("Stop");
stopButton.setBounds(150, 50, 125, 30);
stopButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
timer.stop();
countdownLabel.setText("01:00");
timerCount = 59;
}
});
add(countdownLabel);
add(startButton);
add(stopButton);
setVisible(true);
}
}
This happens because you are adding an ActionListener to the Timer every time that you press the button. So, since a Timer allows multiple listeners, everyone of them gets notified when the timer ticks.
To solve the problems you could just instantiate a new Timer every time you press the start button (timer = new Timer()). Or add the ActionListener just once in your JFrame constructor . Or even remove the listener (but you should save a reference to it somewhere).
Essentially, what I have coded is a puzzle game.
It contains an image , and the image is further divided into 9 pieces which is placed onto JPanel containing a 3x3 JButton GridLayout. Initially, the 9 buttons are empty. When the user clicks "Start Game", the 9 buttons will then show the images on the buttons.
I used setPreferredSize() to set the size of the JPanel containing the 9 empty JButtons. After that, I used Inset ( 0,0,0,0 ) to make the button's contents fill the entire button.
But now, when I want to add the imaged buttons to replace the empty buttons when the user clicks "Start Game" , it doesn't work.
I think this is because the setPreferredSize() I set earlier on is preventing the Insets values from working.
I inserted some system.out.println values to check if the method is running, it runs, but the image still refuses to appear on the buttons when user clicks "Start Game" .
public class GameFrame extends JFrame implements ActionListener {
private JButton button1;
private JButton[] button = new JButton[9];
private Insets buttonMargin;
private boolean testImageMethod;
private JPanel puzpiece;
public GameFrame(){
//.. coding ..
// create new buttons - button1
button1 = new JButton("Start Game");
// add action event to "Start" button
button1.addActionListener(this);
// creates a new panel for the splitted puzzle pieces
puzpiece = new JPanel();
puzpiece.setLayout(new GridLayout(3,3));
// check if testImageMethod boolean ( in setupImage() ) is true,
//if it isn't, adds 9 buttons w/o images.
for(int a=0; a<9; a++){
if(testImageMethod){
}
else{
// adds 9 buttons without images
button[a] = new JButton();
puzpiece.add(button[a]);
puzpiece.setPreferredSize(new Dimension(500,200));
}
}
// adds puzpiece panel into the frame
this.add(puzpiece,BorderLayout.WEST);
//.. coding ..
}
public void actionPerformed(ActionEvent e){
if (e.getSource() == button1){
// puzpiece.button.setVisible(false);
//puzpiece.remove(button);
// call setImage() method
setImage();
for(int a=0; a<9; a++){
// adds the new 9 buttons with images into panel
puzpiece.add(button[a]);
// test if method is running
System.out.println("qq");
}
}
else{
System.out.println("bbb");
}
}
// method setImage() divides the image into subimages
public void setImage(){
//.. coding ..
// test if method is running
System.out.println("a");
setupImage( count++, sc );
}
// method setupImage() adds the subimages to the buttons
private void setupImage( int a, Image wi )
{
// test if method is running
System.out.println("d");
buttonMargin = new Insets( 0, 0, 0, 0 );
button[a] = new JButton( new ImageIcon( wi ) );
button[a].setMargin( buttonMargin );
// test if method is running
System.out.println("e");
} // end method setupImage()
}
I'm not sure I know exactly what you're doing but, ...
It appears that you are populating a JPanel with a 3x3 grid of plain JButtons,
and that on button press you are adding in JButtons that display an image.
But I don't see you removing the original buttons before adding new buttons.
Nor do I see you call revalidate() and then repaint() on the puzpiece JPanel after changing components.
And even more importantly, why swap JButtons when it's much easier to swap ImageIcons in JButtons that are already held by the puzpiece JPanel? This is something that I recommended in comment 10 minutes ago but am now making an answer.
Simply setIcon for the said JButton, don't add JButton anew to the JPanel, already visible
A small example for the same :
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
/**
* Created with IntelliJ IDEA.
* User: Gagandeep Bali
* Date: 1/19/13
* Time: 10:05 AM
* To change this template use File | Settings | File Templates.
*/
public class ButtonImageTest
{
private Icon infoIcon = UIManager.getIcon("OptionPane.informationIcon");
private Icon errorIcon = UIManager.getIcon("OptionPane.errorIcon");
private JButton button;
private int counter = 1;
private void displayGUI()
{
JFrame frame = new JFrame("Button Image Test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel contentPane = new JPanel();
button = new JButton();
button.setBorderPainted(false);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (counter % 2 != 0)
{
button.setIcon(errorIcon);
counter = 2;
}
else
{
button.setIcon(infoIcon);
counter = 1;
}
}
});
contentPane.add(button);
frame.setContentPane(contentPane);
frame.setSize(100, 100);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String... args)
{
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new ButtonImageTest().displayGUI();
}
});
}
}
How do I make the two buttons that are displayed reset / pause the timer? The timer works but I want to change the code for the buttons so that they will change the timer instead of outputting to the console. Thank you.
CODE:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class createWindow extends JFrame implements ActionListener
{
public static void main(String[] args)
{
new createWindow();
}//end main
createWindow()
{
super("Frame");
setSize(400,70);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new FlowLayout());
show();
final JLabel time = new JLabel("Timer");
JButton reset = new JButton("Reset timer");
JButton pause = new JButton("Pause timer");
reset.setActionCommand("resetClicked");
pause.setActionCommand("pauseClicked");
reset.addActionListener(this);
pause.addActionListener(this);
add(pause);
add(time);
add(reset);
long start = System.currentTimeMillis();
while (true)
{
long timer = System.currentTimeMillis() - start;
final int seconds = (int) (timer / 1000);
String display = Integer.toString(seconds);
time.setText(display);
}//end while loop
}//end constructor
#Override
public void actionPerformed(ActionEvent e)
{
String buttonClicked = e.getActionCommand();
if(buttonClicked.equals("resetClicked"))
{
System.out.println("The reset button was clicked"); //Change to reset timer
}
else if(buttonClicked.equals("pauseClicked"))
{
System.out.println("The pause button was clicked"); //Change to pause timer
}
}//end listener
}
Don't use an infinite while loop. This blocks the EDT. Instead use a Swing Timer. This will give you control to start and stop the Timer.
Stopwatch Example
Side Notes:
Don't use JFrame.show as that method is deprecated. Use JFrame.setVisible instead. Also make this call when all components have been added to the frame.
The functionality for the JButtons is sufficiently different to warrant using separate ActionListener instances for each button.
The preferred approach is to use a JFrame instance directly rather then extending it.
Class names in Java begin with uppercase so createWindow would become CreateWindow.