Using same button to enter different text in textfield - java

I'm working on a project to insert numbers based on the number of button clicks using a counter. There's only one single button involved. When that button is pressed once, it should enter 1 in the text field. If that button is pressed again within 3 seconds, 1 should be replaced with 2. If it is pressed after 3 seconds, then the next digit should be entered in the same fashion. I've added my code below.
I'm having some trouble with this program. When i press the button twice within 3 seconds, it enters "12" in the JTextField. Also I'm having trouble to reset the counter after one digit is entered.Hope you understand my question.
package timertry;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;
public class TimerTry extends JFrame implements ActionListener{
public JFrame panel1;
JTextField tf;
JButton button;
int counter=0;
public TimerTry() {
panel1=new JFrame("Single button keypad try");
panel1.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
tf=new JTextField();
tf.setEnabled(false);
tf.setHorizontalAlignment(JTextField.CENTER);
button=new JButton();
}
public void launchFrame(){
panel1.setLayout(null);
panel1.setVisible(true);
panel1.setExtendedState(JFrame.MAXIMIZED_BOTH);
panel1.add(tf);
tf.setSize(300, 50);
tf.setLocation(500, 150);
tf.setEnabled(false);
tf.setHorizontalAlignment(JTextField.CENTER);
panel1.add(button);
button.setSize(360,50);
button.setLocation(900, 250);
button.setLabel("Press");
button.setHorizontalAlignment(JTextField.CENTER);
button.addActionListener(this);
}
public static void main(String[] args) {
// TODO code application logic here
TimerTry tt=new TimerTry();
tt.launchFrame();
}
#Override
public void actionPerformed(ActionEvent e) {
Thread thread=new Thread(){
#Override
public void run(){
try{
sleep(3000);
counter++;
if(counter==1){
tf.setText(tf.getText()+counter);
}
else if(counter==2){
tf.setText(tf.getText()+counter);
}
else if(counter==3){
tf.setText(tf.getText()+counter);
}
else {
tf.setText(tf.getText()+counter);
}
}
catch(Exception ex){
ex.printStackTrace();
}
}
};
thread.start();
}
}

Here's your problem:
if(counter==1){
tf.setText(tf.getText()+counter);
}
else if(counter==2){
tf.setText(tf.getText()+counter);
}
else if(counter==3){
tf.setText(tf.getText()+counter);
}
else {
tf.setText(tf.getText()+counter);
}
Just add tf.setText(""); before each tf.setText(tf.getText() + counter);
Or even better, change your try-catch for this one.
try{
sleep(3000);
counter++;
tf.setText(String.valueOf(counter));
}
catch(Exception ex){
ex.printStackTrace();
}
instead of getting text from tf just set text, it will replace the text it had, instead of adding it again.
Your program does:
1 clic
tf = 1
then you get in an imaginary String let's call it textOfTF
textOfTF = 1
2 clic
textOfTF = 1 (because you get it from tf.getText()) 2
So
textOfTF = 12
And so on.
And as a recommendation don't use thread.sleep() on swing applications, I would recomend using Swing Timer.
thread.sleep() will make your application to freeze, while a swing timer don't.

There are a number of problems with your current approach....
You are spawning a new, independent, Thread each time the button is clicked. Each Thread waits for 3 seconds and the increments the counter regardless
tf.getText()+counter is actually converting the counter to String before it concatenates the result. This means if the text is "1" and the counter is "2", the value will be converted to "12", not "3". Instead, you should just convert the counter to a String directly
There are a number of ways you might resolve this problem...
You could check the current time against the last time the button was clicked, if the value is less then 3 seconds, you can increment the counter, otherwise you would need to reset and start again.
You could use a Swing Timer, which is set to a non-repeating delay of 3 seconds. When the button is clicked, you would restart this timer and increment the counter. When the timer is finally triggered, you would reset the counter to 0

If i did understood you correctly this should be the answer you are looking for. Please comment if something is wrong ! So assume we run the program for 6 seconds , which is divided into 2 period these are 0 -> 3 -> 6 , if you keep pressing the button between 0 and 3 the jtextfield changes to single number display but after 3 seconds another 3 seconds starts actually so there is no before and after within your logic , they cancel each other , so if you don't press the button until 6 seconds 1 and 2 will be displayed. You are able to press 3secondsbutton as much as you can for each 3 seconds which will only change the display mode to the single value. Actually the display mode is changes from multiple numbers to single number or vice versa for each 3 seconds which depends on button pressed or not. If you want to change multiple number display start from the last value , I mean not from beginning you need keep the last value and start displaying from that point so you might need to make some modification on below code.
Your Fields Should be like this
int count=0;
String currenttext = "";
boolean key;
int seconds = 0;
Start Button Action
private void startbuttonActionPerformed(java.awt.event.ActionEvent evt) {
timer();
threesecondsbutton.setEnabled(true);
}
Timer Calling Method
public void timer(){
timer.setInitialDelay(3000);
timer.start();
}
Overide Timer
private Timer timer = new Timer(3000, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// Single Display
if(key==true)
{
count++;
currenttext = currenttext + Integer.toString(count);
jTextField1.setText(Integer.toString(count));
}
// Multi Display
else
{
count++;
currenttext = currenttext + Integer.toString(count);
jTextField1.setText(currenttext);
}
seconds = seconds + 3;
jLabel3.setText(Integer.toString(seconds));
key = false ;
}
});
3 Seconds Button This Button Sets the key to check the button is pressed within 3 seconds or after 3 seconds
private void threesecondsbuttonActionPerformed(java.awt.event.ActionEvent evt) {
count++;
currenttext = currenttext + Integer.toString(count);
jTextField1.setText(Integer.toString(count));
key = true;
}

Related

Adding a new button after an event

Writing a program to increment a counter when a +1 button is pressed, then when the counter reaches a certain number, remove the +1 button and replace it with a +2 button and so on. I create both buttons at first but just set btnCount1 to setVisible(false). When the certain number passes, I make btnCount invisible and btnCount1 visible and increment by two from there. When it reaches 10 clicks, the btnCount disappears, but btnCount1 does not appear.
I have tried making an if(arg0.equals(btnCount1)), and incrementing by two from there. I tried putting the add(btnCount1) inside the else if statement to create it after the elseif condition is true.
public class AWTCounter extends Frame implements ActionListener
private Label lblCount;
private TextField tfCount;
private Button btnCount;
private Button btnCount1;
private int count = 0;
public AWTCounter() {
setLayout(new FlowLayout());
lblCount = new Label("Counter");
add(lblCount);
tfCount = new TextField(count + "",10);
tfCount.setEditable(false);
add(tfCount);
btnCount = new Button("Add 1");
btnCount1 = new Button("Add 2");
add(btnCount);
add(btnCount1);
btnCount1.setVisible(false);
btnCount.addActionListener(this);
btnCount1.addActionListener(this);
setTitle("AWT Counter");
setSize(500,500);
}
public static void main(String[]args) {
AWTCounter app = new AWTCounter();
}
public void actionPerformed(ActionEvent arg0) {
if(count <= 10) {
++count; //Increase the counter value
tfCount.setText(count + "");
}else if(count > 10) {
btnCount.setVisible(false);
btnCount1.setVisible(true);
count += 2;
tfCount.setText(count + "");
}
}
The better solution here is to just have one button object and a separate variable for the current increment amount. When you hit the required count, increase the increment amount and change the button's label to the new value.
There are also a few other things you could do better here.
Use String.valueOf() instead of int + "" for String representations of integers if you're not adding words before or after the integer.
Don't add obvious comments for code. (e.g. 'increment variable x', 'set textString to the new value')
Use descriptive names for method parameters and variables.
Use Labels instead of TextFields for text that doesn't need to be editable or selectable like counter displays.
I'd personally change the name of lblCount to something like lblTitle as well, since changing your tfCount to a Label would logically take up that name and lblTitle makes more sense.
Here's a better way to implement actionPerformed:
private int increment = 1;
private Label lblCount;
...
public void actionPerformed(ActionEvent ignore) {
if(count == 10) {
btnCount.setLabel("Add " + (++increment));
}
lblCount.setText(String.valueOf(count += increment));
}

How do I implement something after a series of button clicks in a certain order and within a certain time period in Android studio if I had 2 buttons

If I had 2 buttons in the android studio and if I wanted to implement something when the 2 buttons are pressed in a certain order and within a certain time period, how would the code be like?
Supposing 2 buttons, button1 and button2 and if pressed in the order button1, button2, button2, button1 implements some activty.
button1.onClick ----(within 1 second)---> button2.onClick ----(within 1 second)---> button2.onClick ----(within 1 second)---> button1.onClick -----> Then do some activity.
I hope this explains what I'm trying to achieve.
Any help is much appreciated. :)
UPDATE
This is what I have so far but I am nowhere close to even sure if this is the right way to go about this
I put an on click listener for both
buttonOne.setOnClickListener(this);
buttonTwo.setOnClickListener(this);
Then
public void onClick(View view) {
if(view == buttonOne) {
//a timer for 1 second {
if(view == buttonTwo) {
//a timer for 1 second {
if(view == buttonTwo) {
//a timer for 1 second {
if(view == buttonOne) {
startActivity(new Intent(this, Some.class));
}
}
}
}
}
}
}
}
The solution works by using handlers and delaying doing something for some time for this case 1 second. Because all the buttons have integer ids then the solution will work to prepare for you an integer array for ids in the right order you can later on loop in an array checking the ids in it comparing it with id of your buttons. Initially all button ids are zero (0), And if they user clicks the button he will be adding the right integer id if he doesnt click any other button in a period of 1 second. All ids in the array will be zero (0) again, except only if the last click is the 4th click and after that you will have to handle your logic by checking the array yourself.
Lets start by declaring the variables we shall use (Remember to read comments):
private Handler handler; //handler to delay all work in 1 second
private Runnable runnable; //runnable this will be doing the job in another thread
private int[] buttonIDs = {0, 0, 0, 0}; //all button ids are zero initially
private int pressNumber=-1; //The user has not clicked anything
These are two methods you will have to add in your class.
The first method:
private void startCounter() {
handler = new Handler();
runnable = new Runnable() {
#Override
public void run() {
if(buttonIDs[3]==0){ // if the last id is still zero lets clear everything and start afresh
clearEverything();
}
}
}
handler.postDelayed(runnable,1000); // we tell it dont execute the code in run until a 1000 milliseconds which is 1 second
}
And the second method is:
private void clearEverything(){
// clear everything will really start everything afresh always call this method first if you want to repeat the game start afresh
pressNumber=-1;
for(int i=0;i < 4;i++) {
buttonIDs[i] = 0;
}
}
The code inside onClick finally is simply this:
if(pressNumber < 3){
pressNumber++; //increment the pressing to another value
buttonIDs[pressNumber] = view.getId(); //use that value as index to button id
if(runnable != null){
handler.removeCallbacks(runnable); // if there was any handler still running cancel it first because we have clicked some button
}
startCounter(); //after click always start counter and remember if the counter finishes it will reset everything
} else{
//Do something here the user has clicked all the buttons 4 times without delaying 1 second each!. The order of button clicks is the integer array buttonIDs and you can clearEverything(); to start again!
}

Clear button only makes counter JLabel blank but does not reset it.

I have made this application:
For example when I click on the clear button when the counter JLabel (pointsAvailable) is 19 then the counter JLabel goes blank as expected, however when I start adding points again it starts from 19 not 40 as set on the start. I would like to make it to reset back to 40 instead of just making it blank
Code for the clear button
private void JButtonActionPerformed(java.awt.event.ActionEvent evt) {
speedPoints.setText("");
attackPoints.setText("");
defencePoints.setText("");
powerPoints.setText("");
agilityPoints.setText("");
focusPoints.setText("");
availablePoints.setText("");
}
Code for Jlabel counter
public class addingPointsUI extends javax.swing.JFrame {
int pointsAvailable=40;
int speed=0;
int power=0;
int focus=0;
int agility=0;
int defence=0;
int attack=0;
Code for buttons +/-: to allow me to add or decrease value "example power - button"
private void powerMinusActionPerformed(java.awt.event.ActionEvent evt) {
if (power > 0 ){
if (pointsAvailable <= 0) {
JOptionPane.showMessageDialog(null, "You are out of available points");
return;
}
power = power - 1;
pointsAvailable = pointsAvailable +1;
availablePoints.setText(String.valueOf(pointsAvailable));
powerPoints.setText(String.valueOf(power));
}else {
JOptionPane.showMessageDialog(null,"You cannot take anymore points from Power");
}
}
Thank your for your kind replies.
Use a JSpinner with SpinnerNumberModel. Change the value of the model. The component will update and further changes will act on the current value of the model.
I can quickly think of two solutions:
1. In the event handler of your clear button include the following:
private void JButtonActionPerformed(ActionEvent evt){
...
pointsAvailable=40;
speed=0;
power=0;
focus=0;
agility=0;
defence=0;
attack=0;
}
This will reset all of your stats.
2. Or you can add an if statement to the listeners of every button that adds or subtracts a stat that will check if the specific statistic is empty. For example, for the speed buttons the code would look like so:
if (speedPoints.getText() == ""){
pointsAvailable += speed;
speed = 0;
}
Found my own solution on google:
private void ClearActionPerformed(java.awt.event.ActionEvent evt) {
speedPoints.setText(String.valueOf(0));
powerPoints.setText(String.valueOf(0));
agilityPoints.setText(String.valueOf(0));
defencePoints.setText(String.valueOf(0));
focusPoints.setText(String.valueOf(0));
attackPoints.setText(String.valueOf(0));
availablePoints.setText(String.valueOf(40));
}
Works perfectly

Change focused button every x seconds in java

I'm looking for the best way to do the following. If someone could point me in the right direction I'd be greatfull.
I have 5 buttons,
Button 1
Button 2
Button 3
Button 4
Button 5
What I'd like to happen is every 5 seconds the focus of the button move one down. So the app starts and Button 1 has focus. Then 5 seconds later button 2 takes focus and so on so on until Button 5 and then back to Button 1. When I say focus I mean that if the space bar was pressed the button would be pressed. Any assistance would be appreciated. Thanks
You could use a java swing timer for this task. Take a look at the example in oracle docs
http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html
You can use the KeyboardFocusManager for this as well. Sample code below using Timer object from java.util. The code below changes focus every 500 ms.
final KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
manager.focusNextComponent();
}
}, 0, 500);
Hope this helps.
You can create thread that sleeps for 5 senconds, then awakes and sets focus to the next button. Store your buttons in array.
final int n = 5;
final int TIMEOUT = 5000;
Button[] buttons = new Button[n];
// fill the array
new Thread() {
for (i = 0; ; i < n ? i++ : i = 0) {
buttons.requestFocusInWindow();
try {
Thread.sleep(TIMEOUT);
} catch(InterruptedException e) {}
}
}.start();
You can also use java.util.Timer

How can I solve delay in showing count down timer(JLabel) in Swing JPanel

I've implemented a count down timer(in function) which updates a label in swing panel every second this is the code:
public void DefineTimer()
{
Action updateClockAction = new AbstractAction() {
public void actionPerformed(ActionEvent e){
JPanelMainGame.this.jLabelSeconds.setText(Integer.toString(JPanelMainGame.this.m_TimerTotalSeconds));
JPanelMainGame.this.jLabelSeconds.setFont(new java.awt.Font("Lucida Handwriting", 1, 36));
JPanelMainGame.this.jLabelSeconds.setForeground(Color.red);
JPanelMainGame.this.jLabelSeconds.setVisible(true);
if( JPanelMainGame.this.m_TimerTotalSeconds >0)
{
JPanelMainGame.this.m_TimerTotalSeconds--;
}
else if ( JPanelMainGame.this.m_TimerTotalSeconds == 0)
{
JPanelMainGame.this.m_Timer.stop();
JPanelMainGame.this.jLabelSeconds.setText("0");
System.out.println("!m_WasGameDecisived: "+!m_WasGameDecisived);
JPanelGameApplet gameApplet = (JPanelGameApplet) getTopLevelAncestor();
//Checking whether time ended for both players and no solution was recieved
if(gameApplet.GetJPanelChooseGame().GetGameType() == eGameType.Net)
{
gameApplet.GetClinetThread().UpdateServerOfTimeEnded();
if (!m_WasGameDecisived)
{
//
System.out.println("Tie - No one had a solution in the given time");
System.out.println("Before send request to solve - Is Socket Closed:"+((JPanelGameApplet)
gameApplet.GetClinetThread().SendRequestToClosePlayerThreadAndRemoveItFromPlayersOnServer();
((JPanelGameApplet)getTopLevelAncestor()).GetDJ().stop();
Menu.BrowseTo(PanelMenuNumber.k_ChooseGame, JPanelMainGame.this.getParent());
((JPanelGameApplet)getTopLevelAncestor()).GetDJ().play(0);
}
}
else if(gameApplet.GetJPanelChooseGame().GetGameType() == eGameType.Single)
{
JPanelMainGame.this.showPopUpSelectionBar();
}
}
((JPanelGameApplet)getTopLevelAncestor()).GetNetMainGame().Initialize();
}
};
m_Timer = new Timer(1000, updateClockAction);
}
Now my problem is in another part of my code when I want to to the following things:
case ProtocolMessages.k_StartGame:
m_GameApplet.GetJpanelStartNetGame().DefineTimer();
m_GameApplet.GetJpanelStartNetGame().GetTimer().start();
m_GameApplet.ShowBoardToSolve();
Menu.BrowseTo(PanelMenuNumber.k_NetPlayersGameStart,m_GameApplet.GetJPanelNetGameSetting().getParent());
m_GameApplet.GetDJ().Next();
break;
So The problem is when I want to start a game, I'm defining my timer and allocating it,
give it start command and going to the screen that I should see there the timer (JLabel updating).
And still although it should be already counting (even before that screen that shows the timer) I still got delay: I get the panel that show the timer, and after about two seconds the Jlabel appear and start to count down.
I think that it is because the event dispatch thread that is not updating immediately the Jlabel in the time I'm doing Jlabel.setText()
Any suggestions of how can I start a game without delay in showing the Jlabel?
Thanks
Call SwingUtilities.invokeAndWait frm the thread to set the label text.

Categories