Is there a way to use a timestamp or other feature to determine what action is carried out?
e.g. when a button is clicked 'A' is performed unless the button has been clicked within the last second, otherwise perform B
You can use System.currentTimeMillis(), it returs time in millisecond,
e.g.
long last_click = 0;
// this is you interval time in milliseconds
long myTimeMillis = 1000;
// ... ... ...
// inside button click function
long time = System.currentTimeMillis()
if(time-last_click > myTimeMillis){
do_taskA();
}else{
do_taskB();
}
last_click = time;
Related
I have to call a method in the run method of a thread 50 times in one second, the problem is, i am only allowed to use sleep as a method!
Now the problem is how can i do that, other threads here for instance:
java- Calling a function at every interval
do that with a timer.
With a timer its easy. But i am only allowed to use sleep as a method...
while (true) {
long t0 = System.currentTimeMillis();
doSomething();
long t1 = System.currentTimeMillis();
Thread.sleep(20 - (t1-t0));
}
t1 minus t0 is the time you spent in 'doSomething', so you need to sleep for that much less than 20 mS.
You probably ought to add some checks for t1-t0 > 20.
You cannot avoid jitter in timing based on System.currentTimeMillis() (or, based on any other system clock).
This solution will not accumulate error due to jitter (unlike another answer here that measures how long the task actually took on each iteration of the loop.) Use this version if it's important for the task to be performed exactly the right number of times over a long span of time.
long dueDate = System.currentTimeMillis();
while (true) {
performThePeriodicTask();
dueDate = dueDate + TASK_PERIOD;
long sleepInterval = dueDate - System.currentTimeMillis();
if (sleepInteval > 0) {
Thread.sleep(sleepInterval);
}
}
I am relatively new to programming, and to help myself I am making a personal project.
I am using Javafx to build drum machine, which allowing the user to program a sequence of beats.
I have constructed sets of rows which each will function as a programmable beat sequencer for each corresponding instrument, with each row consisting of 16 buttons. if that button is pressed, the button is activated, and it will produce the instrument's sound when the loop passes through that point.
for reference this piece of kit is similar to what i wish to construct :
https://images-na.ssl-images-amazon.com/images/I/81RctDCP38L._AC_SL1500_.jpg
Each button is assigned to a hashmap; the Key is an integer from 0-16, while the value is the button's characteristics itself.
The drum machine loops after 4 bars/ 16 buttons.
To trigger the event and to cause the instrument to play, the time (as a fraction of all buttons/16) will match the key of a button. once this occurs, the sound plays. the method to do this is below:
public void beatState(Button button, String filename) {
EventHandler handler = new EventHandler() {
#Override
public void handle(Event event) {
soundGeneration sound = new soundGeneration(filename);
// if the corresponding buttons key (on a range of 0-16) matches the time as a fraction (0-16)
// and if the button text is on (activated by clicking the pad)
if (button.equals(map.get(time.timeToFraction())) & button.getText().equals("On")) {
// plays the file
sound.play();
// when duration of animation is set lower the filename prints more frequently
// or sometimes not printed/sound played when the duration is higher
System.out.println(filename);
}
}
};
// as i increase the duration of the animation , the program becomes both slower but returns
// both the sound file and prints the filename more often
Timeline animationButton = new Timeline(new KeyFrame(Duration.millis(100), handler));
animationButton.setCycleCount(Timeline.INDEFINITE);
animationButton.play();
}
I'll next provide the time element:
public Integer timeToFraction(){
labelFormat();
new AnimationTimer() {
#Override
public void handle(long now) {
// time elapsed since program execution
double elapsedMillis = (System.currentTimeMillis() - startTime);
// converts to long
// multiplies the value to privide a fraction
long numerator = (long) ((elapsedMillis/1000)*8.33);
// value below denominates the time it takes to travel 4 beats at 125 beats per minute
double denominator = 1.92;
// converts below to show as a fraction
long denominatorToBeat =(long) Math.round(denominator * 8.3);
// if the elapsed time raises over 16
// resets numerator
if (numerator> denominatorToBeat) {
startTime = System.currentTimeMillis();
elapsedMillis = (System.currentTimeMillis() - startTime);
}
// converts from long to to allow for hashmap matching against button position
fractionTime = (int) numerator;
}
}.start();
return fractionTime;
}
When the values match up the beat plays, achieving my aim; however, it plays multiple times, and irregular in relation to the beat.
I assume that the animation timer repeat value in milliseconds is what causes this; I decrease it, there are more unwanted repeated sounds. I increase it and notes sometimes are not counted due to the animation passing over the value before it triggers.
I want the code to trigger the sound file when it passes over the button, more specifically when the Integer value of the hashmap the button corresponds to matches the time fraction.
I have spent hours researching and reading the documentation and for an easy problem it is becoming incredibly difficult to work around. Given that this project is seen in a multitude of portfolios and music development software i am sure there is a simple fix to my issue.
Thanks for taking the time.
Your approach in general is wrong, as you are abusing animation timers to do something not related to the GUI. You have to decouple the logic from the GUI.
I.e. The object which controls the timing and playing the sounds should have nothing to do with the buttons or any GUI. It should have some methods to set / clear a sound at particular interval, and then expose its state using properties, e.g. an ObjectProperty with some class describing the current tones being played.
The buttons should call the methods to set / clear tones, and you can add a change listener to the ObjectProperty to update the buttons appearance based on the state.
I'm making fast forward button in my Mp3 player. I wrote already code for this, but have problem how to implement timer to jump 5% forward? I mean when I press button timer should jump 5% forward of total long song. This is my fastForward method.
public void FastForward(){
try {
//songTotalLength = fis.available();
fis.skip((long) ((songTotalLength * 0.05)));
} catch (IOException e) {
e.printStackTrace();
}
}
And here is the button method:
private void jButton3ActionPerformed(ActionEvent e) {
mp3.FastForward();
if(mp3.player.isComplete()){
bar = 100;
}
jProgressBar1.setValue((int)bar);
bar+=5;
}
And this one is for timer:
private void setTime(float t) {
int mili = (int) (t / 1000);
int sec = (mili / 1000) % 60;
int min = (mili / 1000) / 60;
start.set(Calendar.MINUTE, 0);
start.set(Calendar.SECOND, 0);
end.set(Calendar.MINUTE, 0 + min);
end.set(Calendar.SECOND, 0 + sec);
timer = new javax.swing.Timer(1000, new TimerListener());
percent = (float)100/(min*60+sec);
}
You're already redundantly tracking progress in two variables fis and bar. For the sake of good design, use one of those to determine elapsed time rather than using yet another variable for the same purpose.
but have problem how to implement timer to jump 5% forward?
You seem to have mistaken the purpose of a Timer. According to the Timer class documentation, it:
Fires one or more ActionEvents at specified intervals.
So the timer is not meant to keep track of how much time has elapsed. It will simply invoke the actionPerformed(ActionEvent) method of your TimerListener once per second (every 1000 milliseconds) as you have it configured.
For a more complete answer, please post the code for your TimerListener class.
Notes
It seems that your setTime(float) method is meant to be called repeatedly, so this method should not be initializing the timer variable. Rather initialize the timer once and leave it alone to do its job.
I'm assuming you intended the supplied float parameter t to represent microseconds.
The float data type has only 7 digits of precision. This could be fine since you're interested only in minutes and seconds, otherwise float is only good for up to about four months of seconds before losing accuracy.
It seems like you wanted your button click handler to do this (increment bar sooner):
private void jButton3ActionPerformed(ActionEvent e) {
mp3.FastForward();
bar+=5; // increment bar before checking complete, and before setting progress
if(mp3.player.isComplete()){
bar = 100;
}
jProgressBar1.setValue((int)bar);
}
I have set up an onTouchListener which allows the user to click textView2 exactly 10 times, as shown below. My goal is to measure the time between touch 1 and touch 2, and store it as a variable, say time1. However, I'm not quite sure how to do this. One idea I had was setting up a variable, i, that measures the number of times the TouchListener was clicked. I was thinking of potentially measuring the time that i contained a particular value (for example, if i was equal to 1 for 1 second, this means the time between touch 1 and touch 2 was 1 second). However I'm not sure how to implement this, and I'm not even sure if this is the correct method. Does anyone know how to solve this problem?
.java file
public class MainActivity extends Activity {
int i;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView textView2 = (TextView)findViewById(R.id.textView2);
i=0;
textView2.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN){
i++;
if (i==10) textView2.setOnTouchListener(null);
}
return false;
}
});
}
In your class
private long pressTime = -1l;
private long releaseTime = 1l;
private long duration = -1l;
Then in your onTouch method
if(event.getAction() == MotionEvent.ACTION_DOWN){
pressTime = System.currentTimeMillis();
if(releaseTime != -1l) duration = pressTime - releaseTime;
}
else if(event.getAction() == MotionEvent.ACTION_UP){
releaseTime = System.currentTimeMillis();
duration = System.currentTimeMillis() - pressTime;
}
Now you have your duration between touch events:
Duration when you press down is the time between the last time you released and the current press (if you have previously pressed down and released the button).
Duration when you release is the time between the last time you pressed down and the current release time.
-Edit-
If you need to know the difference in time of all events you can just do something like
private long lastEvent = -1l;
private long duration = -1l;
Then in onTouch event
if(lastEvent != -1l) duration = System.currentTimeMillis() - lastEvent;
lastEvent = System.currentTimeMillis();
You can also create a list of durations
private List<Long> durations = new ArrayList<Long>();
and in onTouch instead of duration = ... do
durations.add(System.currentTimeMillis() - lastEvent);
This could be useful for checking all durations between all sequential events. For example, if you want to know the time between pressing down, dragging, stopping dragging, starting dragging, and then lifting up you could check your list after you lift up for every time in question instead of having to constantly check a single duration.
You may want to keep a record of events in a List. The objects stored in this list would keep the timestamp of the touch event, and since UI events are dispatched by a single thread and the clock is monothonic, you are guaranteed that event at N + 1 has a later (at most equal) timestamp than event at index N.
I'm not sure about how you clean this list, however. It depends on how and why you read events, which in turn depends on what you want to do with the delay between two subsequent touch.
For example, if you just wanted to display the time since last touch, a simple code like this could be enough:
public class MyActivity {
private int times = 0;
private long lastTimestamp;
private void onTouchEvent(Event evt) {
if (times > 0) {
long delay = evt.getTimestamp() - lastTimestamp;
// do something with the delay
}
lastTimestamp = evt.getTimestamp();
times++;
}
}
I´ve two buttons and I want to count the time between two clicks. I know how to do that once:
Long starttime = System.currentTimeMillis();
Long endtime = System.currentTimeMillis();
Long differenz = ((endtime-starttime) / 1000);
Now, I want on the second click, that the count starts from zero again until the first button is clicked. Then, measure the time between first and second button click and so on.
Maybe it´s a really simple thing but I don´t know how to do...
EDIT: Ok, I try to make it clear:
I have Button A and B. I want the user to alternately push button A and B. When the user clicks on Button A, I want a timer to measure the time until B is clicked. Until here, everything is clear to me.
Now I want that the time between the click on B till the click to A is measured, always alternated between A and B.
I don´t know what to do after the click on B that the time is measured again until A.
Class members
boolean mButtonAClicked;
boolean mButtonBClicked;
long mStartTime = 0;
When Button A is clicked
if (mButtonAClicked)
{
// button A is clicked again, stop application
}
else
{
mButtonAClicked = true;
mButtonBClicked = false;
if (mStartTime != 0) // Button B was clicked
{
Long endtime = System.currentTimeMillis();
Long differenz = ((endtime-starttime) / 1000);
mStartTime = System.currentTimeMillis();
}
}
When Button B is cliked
if (mButtonBClicked)
{
// button B is clicked again, stop application
}
else
{
mButtonBClicked = true;
mButtonAClicked = false;
if (mStartTime != 0) // Button A was clicked
{
Long endtime = System.currentTimeMillis();
Long differenz = ((endtime-starttime) / 1000);
mStartTime = System.currentTimeMillis();
}
}
Create a field to hold last time each was pressed.
long aMillisPressed;
long bMillisPressed;
When Button A is clicked:
aMillisPressed = System.currentTimeMillis();
long timeElapsedSinceBPressed = aMillisPressed - bMillisPressed;
And when B is clicked:
bMillisPressed = System.currentTimeMillis();
long timeElapsedSinceAPressed = bMillisPressed - aMillisPressed;