This question already has answers here:
What is a debugger and how can it help me diagnose problems?
(2 answers)
Closed 4 years ago.
I am working on this program that calculates the Beats per Minute (BPM) when you click the button. When you click two times, it is supposed to display the current BPM, and display the new one with every click after that. What the problem is, though, is that the display isn't changing. What do I need to do?
Here is my code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
public class BPM extends JPanel implements ActionListener {
JLabel label;
public String display;
public int bpm;
public int buttonPressed;
public int time1;
public int time2;
public int time3;
public int counter[];
public void addComponents(Container pane) {
JPanel buttons = new JPanel();
JButton bpmButton = new JButton("Click");
bpmButton.setSize(new Dimension(100, 50));
bpmButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
buttonPressed++;
counter = new int[2];
if (buttonPressed == 1) {
counter[0] = (int)(System.currentTimeMillis());
} else if (buttonPressed == 2) {
counter[1] = (int)(System.currentTimeMillis());
calculateTimeBetweenClicks();
setTime();
} else {
counter[0] = counter[1];
counter[1] = (int)(System.currentTimeMillis());
calculateTimeBetweenClicks();
setTime();
}
}
});
display = "0";
label = new JLabel(display, SwingConstants.CENTER);
label.setFont(label.getFont().deriveFont(100.0f)); // original 45
pane.add(label, BorderLayout.PAGE_START);
pane.add(bpmButton, BorderLayout.CENTER);
}
// Calculates the difference between the two saved clicks
public void calculateTimeBetweenClicks() {
if (buttonPressed == 1) {
time1 = counter[0];
} else {
time1 = counter[0];
time2 = counter[1];
}
time3 = time2 - time1;
}
// Calculates the BPM and changes the display accordingly
public void setTime() {
bpm = 60000 / time3;
display = "" + bpm + "";
label.setText(display);
}
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
public static void createAndShowGUI() {
// Creates the window
JFrame frame = new JFrame("BPM Calculator");
frame.setPreferredSize(new Dimension(300, 200)); // original (250, 130)
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Adds the components to the content pane
BPM window = new BPM();
window.addComponents(frame.getContentPane());
//Displays the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
// Turns off bold text
UIManager.put("swing.boldMetal", Boolean.FALSE);
// Allows the components to be used and interacted with
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
The problem is in your addComponents method, you are creating a new array on each and every button click (so you end up with a new and empty array). This is throwing off your calculation. Simply move the instantiation of your array to somewhere outside of the ActionListener like this...
public void addComponents(Container pane) {
JPanel buttons = new JPanel();
counter = new int[2]; //Move this line to here...
JButton bpmButton = new JButton("Click");
bpmButton.setSize(new Dimension(100, 50));
bpmButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
buttonPressed++;
if (buttonPressed == 1) {
counter[0] = (int)(System.currentTimeMillis());
} else if (buttonPressed == 2) {
counter[1] = (int)(System.currentTimeMillis());
calculateTimeBetweenClicks();
setTime();
} //Removed the else - see edit below :-)
}
});
Additional
Your code as-is seems to get a litle confused after the 2nd click (the first BPM calculation) as it seems to take that 2nd click as the first click of the next set of 2 clicks if you get what I mean. I'm not sure if this is intended behaviour, but if not, I would reset everything in the calculateTimeBetweenClicks method after you've calculated the correct bpm ready for a new set of 2 clicks...
// Calculates the difference between the two saved clicks
public void calculateTimeBetweenClicks() {
if (buttonPressed == 1) {
time1 = counter[0];
} else {
time1 = counter[0];
time2 = counter[1];
//Reset here ready for next 2 clicks...
counter[0]=0;
counter[1]=0;
buttonPressed = 0;
}
time3 = time2 - time1;
}
Related
I have a program which uses 3 radiobuttons to switch between 3 incrementing values for a counter, here time.
I want to change status when a radiobutton is pressed, and it does so, but only for a fraction. When launching the program will keep printing
0
Normal
2
Normal
4
Normal
6
etc. When I press the button slow it prints CHANGE Slow once but keeps incrementing with 2 and still prints Normal every time.
How can I have this permenently switch to a different value for status, and a different increment, until I choose another radiobutton again?
package daynightcycle;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
/**
* Day/night cycle with visuals. Adjustable speed and time inserts.
* Optional date or daycounter later
* #author rogie
*/
public class DayNightCycle extends JFrame implements Runnable{
//JFrame entities
private JPanel animationPanel;
public JRadioButton button;
public JRadioButton button2;
public JRadioButton button3;
public int time = 0;
public String status = "Normal";
public static void main(String[] args) {
DayNightCycle frame = new DayNightCycle();
frame.setSize(2000, 1300);
frame.setLocation(1000,350);
frame.createGUI();
frame.setVisible(true);
frame.setTitle("Day/Night Cycle, Rogier");
(new Thread(new DayNightCycle())).start();
}
private void createGUI() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
Container window = getContentPane();
window.setLayout(new FlowLayout() );
animationPanel = new JPanel();
animationPanel.setPreferredSize(new Dimension(2000, 900));
animationPanel.setBackground(Color.black);
window.add(animationPanel);
JRadioButton option1 = new JRadioButton("Slow");
JRadioButton option2 = new JRadioButton("Normal", true);
JRadioButton option3 = new JRadioButton("Fast");
option1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
System.out.println("CHANGE");
status = "Slow";
System.out.println(status);
}
});
option2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
status = "Normal";
}
});
option2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
status = "Fast";
}
});
//option2.setFont(new java.awt.Font("Tahoma", Font.BOLD, 30));
//option2.putClientProperty("JComponent.sizeVariant", "huge"); //doesn't work
ButtonGroup group = new ButtonGroup();
group.add(option1);
group.add(option2);
group.add(option3);
add(option1);
add(option2);
add(option3);
pack();
}
public void run() {
while(true){
System.out.println(time);
System.out.println(status);
try
{
Thread.sleep(500);
if (status.equals("Slow")) {
time += 1;
}
else if (status.equals("Normal")){
time += 2;
}
else {
time += 3;
}
}
catch(InterruptedException ex)
{
Thread.currentThread().interrupt();
}
}
}
}
You are creating to DayNightCycle-Objects, the first shows the GUI and the second prints on the console.
Change the line
(new Thread(new DayNightCycle())).start();
to
(new Thread(frame)).start();
public static void main(String[] args) {
final DayNightCycle frame = new DayNightCycle();
frame.setSize(2000, 1300);
frame.setLocation(1000,350);
frame.createGUI();
frame.setTitle("Day/Night Cycle, Rogier");
And then
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
frame.setVisible(true);
}
});
Or in java 8:
EventQueue.invokeLater(() -> frame.setVisible(true));
}
You in effect created a second DayNightCycle.
I made a puzzle game in java Applet, and I need to add a timer that runs for 5 minutes where the player has to solve the puzzle within this time, if not a dialog box will appear asking to retry, so then I need the timer to start again.
Can someone tell me how can I code this.
public void init (){
String MINUTES = getParameter("minutes");
if (MINUTES != null) remaining = Integer.parseInt(MINUTES) * 600000;
else remaining = 600000; // 10 minutes by default
// Create a JLabel to display remaining time, and set some PROPERTIES.
label = new JLabel();
// label.setHorizontalAlignment(SwingConstants.CENTER );
// label.setOpaque(false); // So label draws the background color
// Now add the label to the applet. Like JFrame and JDialog, JApplet
// has a content pane that you add children to
count.add(label);
Puzframe.add(count,BorderLayout.SOUTH);
// Obtain a NumberFormat object to convert NUMBER of minutes and
// seconds to strings. Set it up to produce a leading 0 if necessary
format = NumberFormat.getNumberInstance();
format.setMinimumIntegerDigits(2); // pad with 0 if necessary
// Specify a MouseListener to handle mouse events in the applet.
// Note that the applet implements this interface itself
// Create a timer to call the actionPerformed() method immediately,
// and then every 1000 milliseconds. Note we don't START the timer yet.
timer = new Timer(1000, this);
timer.setInitialDelay(0); //
timer.start(); }
public void start() { resume(); }
//The browser calls this to stop the applet. It may be restarted later.
//The pause() method is defined below
void resume() {
// Restore the time we're counting down from and restart the timer.
lastUpdate = System.currentTimeMillis();
timer.start(); // Start the timer
}`
//Pause the countdown
void updateDisplay() {
long now = System.currentTimeMillis(); // current time in ms
long elapsed = now - lastUpdate; // ms elapsed since last update
remaining -= elapsed; // adjust remaining time
lastUpdate = now; // remember this update time
// Convert remaining milliseconds to mm:ss format and display
if (remaining < 0) remaining = 0;
int minutes = (int)(remaining/60000);
int seconds = (int)((remaining)/1000);
label.setText(format.format(minutes) + ":" + format.format(seconds));
label.setForeground(new Color(251,251,254));
label.setBackground(new Color(0,0,0));
// If we've completed the countdown beep and display new page
if (remaining == 0) {
// Stop updating now.
timer.stop();
}
count.add(label);
Puzframe.add(label,BorderLayout.SOUTH); }
This what I have so far, but my problem is that it doesn't appear in my game. I'm calling the updateDisplay() from actionPerformed
Use Swing Timer it is made for such a scenario
//javax.swing.Timer
timer = new Timer(4000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(mainFrame,
"End Of Game",
"5 minutes has passed",
JOptionPane.ERROR_MESSAGE);
}
});
I prepared a simple example to demonstrate it
Example
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SwingControlDemo {
private JFrame mainFrame;
private JPanel controlPanel;
private Timer timer;
public SwingControlDemo(){
prepareGUI();
}
public static void main(String[] args){
SwingControlDemo swingControlDemo = new SwingControlDemo();
swingControlDemo.showEventDemo();
}
private void prepareGUI(){
mainFrame = new JFrame("Java SWING Examples");
mainFrame.setSize(400,400);
mainFrame.setLayout(new GridLayout(3, 1));
mainFrame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent windowEvent){
System.exit(0);
}
});
controlPanel = new JPanel();
controlPanel.setLayout(new FlowLayout());
mainFrame.add(controlPanel);
mainFrame.setVisible(true);
//javax.swing.Timer
timer = new Timer(4000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(mainFrame,
"End Of Game",
"5 minutes has passed",
JOptionPane.ERROR_MESSAGE);
}
});
}
private void showEventDemo(){
JButton okButton = new JButton("Start Game");
okButton.setActionCommand("OK");
okButton.addActionListener(new ButtonClickListener());
controlPanel.add(okButton);
mainFrame.setVisible(true);
}
private class ButtonClickListener implements ActionListener{
public void actionPerformed(ActionEvent e) {
timer.start();
String command = e.getActionCommand();
if( command.equals( "OK" )) {
System.out.println("Timer started");
}
}
}
}
I'm self learning java beginner
i'm trying to create simple calculator using java swing and i want to create array of JButtons to create all the buttons in the project , i had some issues so i declare all variables outside the constructor
public class SimpleCalculator extends JFrame implements ActionListener {
JButton btnArray[] = new JButton[16];
JLabel nameLabel = new JLabel("Ghanayem's Calculator",
SwingConstants.CENTER);
JTextField txt = new JTextField();
JPanel numPanel = new JPanel(new GridLayout(4, 3, 15, 5));
JPanel opPanel = new JPanel(new GridLayout(4, 1, 0, 5));
JPanel panel = new JPanel(new GridLayout(2, 1, 0, 5));
int counter;
char operation;
double operand1;
double operand2;
like that ,and i think to add actions to buttons inside for-loop no compiler errors every thing is ok
for (counter = 0; counter < 10; counter++) {
btnArray[counter] = new JButton("" + counter);
btnArray[counter].addActionListener(this);
}
and here is action performed implementation
#Override
public void actionPerformed(ActionEvent e) {
txt.setText(txt.getText() + counter);
}
just like that ,when i try to run the program and press any number button the number added to text field is "16" for all buttons, and this is main method
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
SimpleCalculator frame = new SimpleCalculator();
frame.setVisible(true);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setResizable(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
i am getting crazy i don't know what is wrong , please i need your help this my first swing application i am so disperate
thank you
Try something like this (I can't test right now so it may contain some lesser errors):
#Override
public void actionPerformed(ActionEvent e) {
String value = ((JButton)e.getSource()).getText();
Integer intValue = Integer.parseInt(value);
Integer intValue2 = Integer.parseInt(txt.getText());
txt.setText( "" + (intValue + intValue2));
}
#Override
public void actionPerformed(ActionEvent e) {
JButton b = (JButton) e.getSource();
txt.replaceSelection(b.getActionCommand());
}
this is a solution for my question i found here
java-action-listener
#Override
public void actionPerformed(ActionEvent e) {
String value = (JButton) e.getSource().getText();
txt.setText(txt.getText() + value);
}
and this is another solution #Paco Abato helps me to find
My first post, so forgive any incorrect etiquette. I'm currently doing my year end project for school and I need a bit of help. I am making a GUI java app in Netbeans. I have two classes. One is a class that controls a timer, the other is a class that is a scoreboard screen. I need to update the scoreboard timerLabel with the time that is being counted down in the timerClass. Its quite messy as there is another timer label in the Timer class which does update. My problem is that I cannot get timerLabel in MatchScreen() to update. Here is my code :
Timer Class
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
public class TimerClass extends JFrame {
Timer timer;
JLabel promptLabel, timerLabel;
int counter;
JTextField tf;
JButton button;
MatchScreen call = null;
public TimerClass() {
call = new MatchScreen();
setLayout(new GridLayout(4, 4, 7, 7));
promptLabel = new JLabel(""
+ "Enter number of seconds for the timer",
SwingConstants.CENTER);
add(promptLabel);
tf = new JTextField(5);
add(tf);
button = new JButton("Start");
add(button);
timerLabel = new JLabel("waiting...",
SwingConstants.CENTER);
add(timerLabel);
event e = new event();
button.addActionListener(e);
System.out.println("Button pressed");
}
public class event implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.out.println("Action performed");
int count = (int) (Double.parseDouble(tf.getText()));
timerLabel.setText("Time left: " + count);
call.setTimerLabel(count);
System.out.println("Passed count to tc");
TimeClass tc = new TimeClass(count);
timer = new Timer(1000, tc);
System.out.println("Timer.start");
timer.start();
//throw new UnsupportedOperationException("Not supported yet.");
}
/*public void actionPerformed(ActionEvent e) {
throw new UnsupportedOperationException("Not supported yet.");
}*/
}
public class TimeClass implements ActionListener {
int counter;
public TimeClass(int counter) {
this.counter = counter;
}
public void actionPerformed(ActionEvent e) {
counter--;
if (counter >= 1) {
call.setTimerLabel(counter);
} else {
timerLabel.setText("END");
timer.stop();
Toolkit.getDefaultToolkit().beep();
}
}
}
public static void main(String args[]) {
TimerClass gui = new TimerClass();
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.setSize(250, 150);
gui.setTitle("Time Setup");
gui.setVisible(true);
}
}
And now the ScoreBoard Screen
public class MatchScreen extends javax.swing.JFrame {
int redScore = 0, blueScore = 0, blueCat1 = 0,
blueCat2 = 0, redCat1 = 0, redCat2 = 0, winner = 0;
public MatchScreen() {
initComponents();
}
//Determine Winner of the match
public int getWinner() {
if (redScore > blueScore) {
winner = 1;
} else {
winner = 2;
}
return winner;
}
public void setTimerLabel(int a) {
int time = a;
while (time >= 1) {
timerLabel.setText("" + time);
}
if (time < 1) {
timerLabel.setText("End");
}
}
private void jButton13ActionPerformed(java.awt.event.ActionEvent evt) {
//Creates an object of the timerClass
TimerClass gui = new TimerClass();
gui.setSize(300, 175);
gui.setTitle("Time Setup");
gui.setVisible(true);
}
}
Some code that I felt is irrelevant was left out from the MatchScreen().
Many thanks
Managed to solve the general problem. I put all the code into one class. Not ideal, but it works :/ Anyway, deadlines are looming.
Sincere thanks.
You have a while loop in the setTimerLabel method, which I don't think you intended to put there. Also, you take the parameter a and assign it to time and then never use a again, why not just rename your parameter to time and bypass that additional variable?
EDIT
Sorry, I forgot to explain what I'm seeing :P If you say call.setTimerLabel(10) then you hit that while loop (while(time >= 1) which is essentially running while(10 >= 1) which is an infinite loop. Your program is never leaving the method setTimerLabel the first time you call it with a value >= 1.
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