I was making a clock, which displays time in Java, I will show the code below:
public class MyApp extends javax.swing.JFrame {
int timeRun = 0;
/**
* Creates new form MyApp
*/
public MyApp() {
initComponents();
System.out.println("We'll start here!");
new Thread ()
{
public void Run(){
while(timeRun == 0)
{
Calendar cal = new GregorianCalendar();
int hour = cal.get(Calendar.HOUR);
int min = cal.get(Calendar.MINUTE);
int sec = cal.get(Calendar.SECOND);
int AM_PM = cal.get(Calendar.AM_PM);
String time = hour + ":" + min + ":" + sec;
System.out.print(time);
System.out.print("We'll end here!");
}
}
}.start();
}
I have a JLabel, and the other components needed for this JFrame to work.
I also have main set up, although you can't see it in the example above
My issue is, that I can't get a value from time, nor can I print "We'll end here" inside the Run, I'm new to Java, so any help would be much appreciated.
My console prints this:
run:
We'll start here!
BUILD SUCCESSFUL (total time: 6 seconds)
You've created a thread, but you haven't overridden the run method - instead you've created a Run method. Java is case-sensitive. Change this:
public void Run() {
...
}
to this:
#Override
public void run() {
...
}
Using #Override asks the compiler to validate that you really are overriding something - if you'd used that before, you'd have received a compile-time error.
Additionally, I'd recommend implementing Runnable and passing that to the Thread constructor instead of overriding run in Thread itself:
Runnable runnable = new Runnable() {
#Override
public void run() {
...
}
};
new Thread(runnable).start();
Again, if you'd implemented the interface instead of creating an anonymous subclass of Thread, the compiler would have picked up the problem.
EDIT: As noted in comments, your loop is never-ending, too... but you'll see that when it actually gets as far as running.
The thread's method you must override is run. Because that's the one you are inheriting and which is intented to actually run what thread must do.
So:
It's all about inheritance.
Add #Override annotations in such codes. (IDE should have suggested it).
Remember Java is case sensitive.
Stick to Camel notation. In Java, all is supposed to be coded according to it.
4.1 Classes and Interfaces are supposed to start with capital letters.
4.2 Attributes and methods are supposed to start with small letters.
You should have done:
#Override
public void run() {
//Your code here
}
Related
I have now tried to set up a delay in libGDX in three different ways.
First I tried to use a Timer, but if I restart the activity, the timer won't start again. This is a known issue when using GestureDetector: https://github.com/libgdx/libgdx/issues/2274
Then I tried setting up a timer using Gdx.graphics.getDeltaTime in my render method, but this doesn't work for me as I have set it to non-continous rendering. Described in answer #2 set a delay in libgdx game
Finally I tried using a while loop and System.getCurrentTimeMilliseconds, however this prevented the application from recognizing a tap while the while loop was looping.
I have also heard of DelayAction, but how does one implement that into the code? https://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/scenes/scene2d/actions/DelayAction.html
Is there another way of setting a delay? How do one implement DelayAction? Or how does one fix the Timer bug in libGDX?
Inspired by Barodapride's comment, I found a solution where I make a new thread, and put the while loop here. This code will wait for 1000 ms, and then run foo() on the main thread.
new Thread(new Runnable() {
#Override
public void run() {
long time = System.currentTimeMillis();
while (System.currentTimeMillis() < time + 1000){}
Gdx.app.postRunnable(new Runnable() {
#Override
public void run() {
foo();
}
});
}
}).start();
Well i just create an interface like this:
public interface TimeEvents {
public void handleTime(float secondsToEvent,Events event, Object obj);
public void resetTimer();
public void handleEvent(Events event,Object obj);
}
and create a class implementing it for the game entity i want, the Events for my case is an enum with the event to process (Like wait for x seconds, walk for x seconds, fire for x seconds..), the object is the instance of target object i want to handle by event..
public class FooTimeEvents implements TimeEvents{
[...]
private float timeSeconds = 0;
#Override
public void handleTime(float secondsToEvent,Events event, Object obj){
timeSeconds +=Gdx.graphics.getRawDeltaTime();
if(timeSeconds > secondsToEvent){
timeSeconds-=secondsToEvent;
handleEvent(event,obj);
}
}
#Override
public void handleEvent(Events event,Object obj){
switch (event) {
case EVENT_FOO_1:
executeEventFoo1((Foo1Obj)obj);
break;
case EVENT_FOO_2:
executeEventFoo2((Foo2Obj)obj);
break;
default:
break;
}
}
[...]
you call the handleTime on render method of the entity, and the event will only execute each timeSeconds it was set to..
You can use a RunnableAction with a DelayAction. Here are the steps you would take:
Instantiate a RunnableAction and provide it with a Runnable:
RunnableAction runnableAction = Actions.run(new Runnable(){
public void run(){
// Put whatever you want to do here
}
}
Instantiate a DelayAction and provide it with your RunnableAction:
DelayAction delayAction = Actions.delay(secondsOfDelay, runnableAction);
Now in your render or update method you need to tell your delayAction to 'act':
delayAction.act(delta);
Once the delay has passed the code in your runnable should run. I'm sorry if this syntax isn't exactly correct but this should be the easiest way to go. Let me know if something doesn't work for you and I can help.
The plan:
I created a little PreferenceActivity (don't hate me, I'm supporting API 10 and up) and need to display the current usage of local storage data by my app. I did this using a specialized class (a pretty big one, as of the moment) that handles all file operations (it's called FileOperations.java for a reason). Inside this class file there is a method getSize(File file) {...} which does just that. It gets the size of a file (or folder) with this little piece of code:
public long getSize(File file) {
long size = 0;
if(file.isDirectory()) {
for(File child : file.listFiles()) {
size += getSize(child);
}
}
size = file.length();
return size;
}
The general idea was to use this in a background Thread so it doesn't clog the UI even the slightest bit. (I am really annoyed by lagging apps and suffer from them daily)
The problem:
This works just fine. However, as soon as I purge the folder the app stores it's data in using this beauty:
private void purgeLocalStorage() {
new Thread(new Runnable() {
#Override
public void run() {
Looper.prepare();
Log.i("ActivityPrefsLocalStorage.purgeLocalStorage.Thread.Runnable.run", "Started to run");
final String directory = context.getResources().getString(R.string.app_name);
final String usedData = context.getResources().getString(R.string.ActivityPrefsLocalStorage_usedData);
final File file = new File(Environment.getExternalStorageDirectory()+"/"+directory);
final FileOperations FO = new FileOperations(context);
Log.i("ActivityPrefsLocalStorage.purgeLocalStorage.Thread.Runnable.run", "deleting folder: "+file);
if(FO.delete(file)) {
Log.i("ActivityPrefsLocalStorage.purgeLocalStorage.Thread.Runnable.run", file+" deleted");
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(context, R.string.ActivityPrefsLocalStorage_deleteSucces, Toast.LENGTH_SHORT).show();
setTotalLocalDataTexts(usedData+" "+context.getResources().getString(R.string.pref_totalData_default), "");
getUsedStorage();
}
});
} else {
Log.e("ActivityPrefsLocalStorage.purgeLocalStorage.Thread.Runnable.run", "could not delete "+file);
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(context, R.string.ActivityPrefsLocalStorage_deleteError, Toast.LENGTH_SHORT).show();
}
});
}
}
}).start();
}
Things hit the fan...
See, the problem is that my method for reading the size of the folder does not want to function properly when called by the previous method.
Here's a snippet:
private void getUsedStorage() {
new Thread(new Runnable() {
#Override
public void run() {
Log.i("ActivityPrefsLocalStorage.getUsedStorage.Thread.Runnable.run", "Started to run");
final String directory = context.getResources().getString(R.string.app_name);
final String usedData = context.getResources().getString(R.string.ActivityPrefsLocalStorage_usedData);
final File file = new File(Environment.getExternalStorageDirectory()+"/"+directory);
final FileOperations FO = new FileOperations(context);
final DataUsage DU = new DataUsage(context);
Log.i("ActivityPrefsLocalStorage.getUsedStorage.Thread.Runnable.run", "Checking filesize of folder: "+file);
long fileSize = FO.getSize(file);
String usedUnits = DU.getUnit(fileSize, true, false, false);
String usedBytes = DU.getUnit(fileSize, true, true, true);
Log.i("ActivityPrefsLocalStorage.getUsedStorage.Thread.Runnable.run", "filesize of "+file+": "+usedUnits);
setTotalLocalDataTexts(usedData+" "+usedUnits, usedBytes);
}
}).start();
}
However, a quick and easy workaround would be to place it on the UI thread like so:
...blabla code you already read above.
long fileSize = FO.getSize(file);
String usedUnits = DU.getUnit(fileSize, true, false, false);
String usedBytes = DU.getUnit(fileSize, true, true, true);
Log.i("ActivityPrefsLocalStorage.getUsedStorage.Thread.Runnable.run", "filesize of "+file+": "+usedUnits);
runOnUiThread(new Runnable() {
#Override
public void run() {
setTotalLocalDataTexts(usedData+" "+usedUnits, usedBytes);
}
});
}
}).start();
}
And that's where it starts getting interesting. I cannot use non-finals inside the new Runnable(), and I cannot make them final since I want the value to update and not remain stuck at eg. 32MiB (while it has just been purged).
Possible fixes:
I should man up and just use a final. The user will understand they need to refresh the page manually. (oh no...)
Hire... erm. Extend an AsyncTask<Void, Void, Void> to do the work.
My ideal fix:
Someone giving me an awesome snippet of code for free that does all the magic. no, seriously though, I would really appreciate anything apart from my list of possible fixes. There has to be some way to pass the new Runnable() a variable without creating classes and implementing the entire universe? Or is that what I am trying to achieve really a new thing?
TL;DR:
Things go wrong as soon as I call getUsedStorage() from within a new Runnable(). This function is also a background task inside a Runnable, but updates the UI using a private void function that sets it. It only passes variables to this function. and then things fly off the handle(r).
Edit: grammar.
Edit2: Also a pretty interesting thing to note here, I used something similar in another PreferenceActivity, and that one works. (but that one does not update at the press of a button that calls another private something functionName() {new Thread(new Runnable() {public void run() {...});})
There are a couple of ways to use non-finals inside of a Runnable or other enclosed classes.
The first is to change your variables to be members of an enclosing class. This will allow you to use the variables inside the Runnable. An example follows:
public class Foo {
private long time;
public void run() {
time = System.currentTimeMillis();
new Thread(new Runnable() {
#Override
public void run() {
time += 1;
System.out.println("Our current time is: " + time);
}
});
}
}
The other option, and it is quite hacky, is to use a final array with a length of 1. An example of that follows:
public class Foo {
public void run() {
final long[] time = { System.currentTimeMillis() };
new Thread(new Runnable() {
#Override
public void run() {
time[0] += 1;
System.out.println("Our current time is: " + time[0]);
}
});
}
}
As gonemad16 on reddit.com/r/androiddev pointed out, my issue had nothing to do with final vs non final. That was not the reason I was getting an old value. All my variables are given a value, sent to setTotalLocalDataTexts and then go out of scope... nothing is updating their values.. so there is no harm in them being final and no benefit to them being non final...
It was an an issue in getSize()
I thought I had a correct loop there using if file.isDirectory() {...}. It created a directory tree and executed itself using the children it has found. When all items have been scanned the value returns to the function calling it.
This was working just fine for me while I was still running all of my code on the ui thread. Everything was slow. But it worked.
However, I forgot that I removed a very crucial ...} else {...
I believe I removed that one because it caused a stack overflow at some point, so I removed it and I guess forgot to put it back...
And here I was thinking my first SO question wouldn't be a noobish question...
After creating a session, i want to call a method again & again after a specific time - i.e. 5 sec.
But when i call a method it gives me an error. Here is the sample code.
public class RunFunction extends MainScreen{
public RunFunction()
{
//Call Function again and again after 5 sec
setTitle("Timer");
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
BasicEditField b = new BasicEditField("Hello", "");
String a = b.getText();
Dialog.alert("Value " +a);
}
}, 5000);
}
}
I need help related to this. Can you provide any sample code?
From the BlackBerry docs on the Timer class:
A facility for threads to schedule tasks for future execution in a background thread.
So, the first thing to understand is that whatever work you do in the run() method will be run on a background thread. Background threads are not allowed to modify the UI directly. You're probably getting an IllegalStateException by doing that.
Maybe this is just test code, but this code
BasicEditField b = new BasicEditField("Hello", "");
String a = b.getText();
Dialog.alert("Value " +a);
is a little confusing. It creates a BasicEditField, but only uses it to get the String value passed in to it. Just instantiating a field does not add it to a screen. So, you would need to call
add(b);
after this code for the edit field to show. But again, that would be modifying the UI directly. So, in your case, you probably just need to wrap your code with a call to UiApplication#invokeLater():
timer.schedule(new TimerTask() {
public void run() {
// this code executed on background thread -> not UI safe!
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
// this code safely executed on UI thread
BasicEditField b = new BasicEditField("Hello", "");
add(b);
String a = b.getText();
Dialog.alert("Value " +a);
}
});
}
}, 5000);
Next, calling Timer#schedule(TimerTask,long) will only schedule your task to run once, after 5000 milliseconds. If you want it to run again and again, use the version of schedule(TimerTask,long,long) that takes three parameters. The last parameter is the amount of time between each call to your timer task's run() method.
This example on Timer and TimerTask java class provides some insights on what you want to do:
http://javaprogramming.language-tutorial.com/2012/02/demonstrate-timer-and-timertask.html
I'm playing around with Java and I've got myself a class for an NPC in a game. One method is called when they collide with another object:
public void collided_in_to(Entity ent) {
if(ent.equals(game.player)) {
this.speak = "Ouch!";
}
}
What I want to do, which I figured was going to be simple, is set this.speak to "" after a given amount of seconds. Coming from a web background, I was looking for an equivalent of Javascripts setTimeout().
I've tried using various timer snippets, such as using Swing timers, but in that case it seemed like every timer would call the same public void actionPerformed(ActionEvent e) method, and so with multiple timers for different events I had no way to differentiate between them. Others used inline anonymous classes, but then I have no way to pass non-final parameters to it.
Is there something I'm missing for this use case, where I want very small simple things to happen after a set time? (Instance method called, variable set, etc.)
Thanks!
How about writing you own simple Timer? I would think of something like this :
public class Timer {
long start = 0;
long delay;
public Timer(long delay) {
this.delay = delay;
}
public void start() {
this.start = System.currentTimeMillis();
}
public boolean isExpired() {
return (System.currentTimeMillis() - this.start) > this.delay;
}
}
Then instantiate the Timer class as a class member and call start() when you want to start the timer.
In your method you call
public void collided_in_to(Entity ent) {
if(ent.equals(game.player)) {
if(this.timer.isExpired()) this.speak = "";
else this.speak = "Ouch!";
}
}
If you're using a game loop you could simply make a seconds passed verification.
Have you considered threads? Thread.sleep() can be used fairly effectively to time it.
import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;
public class Boggle {
Board board;
Player player;
Timer timer;
boolean active;
static Scanner in = new Scanner(System.in);
public Boggle() {
board = new Board(4);
timer = new Timer();
}
public void newGame() {
System.out.println("Please enter your name: ");
String line = in.nextLine();
player = new Player(line);
active = true;
board.shuffle();
System.out.println(board);
timer.schedule(new timesUP(), 20000);
while(active) {
String temp = in.nextLine();
player.addGuess(temp);
}
}
public void endGame() {
active = false;
int score = Scoring.calculate(player, board);
System.out.println(score);
}
class timesUP extends TimerTask {
public void run() {
endGame();
}
}
public static void main(String[] args) {
Boggle boggle = new Boggle();
boggle.newGame();
}
}
I have the above class which should perform a loop for a given length of time and afterwards invoke an instance method. Essentially I need the loop in newGame() to run for a minute or so before endGame() is invoked on the current instance. However, using the Timer class I'm not sure how I would invoke the method I need on the current instance since I can't pass any parameters to the timertasks run method?
Is there an easy way to do this or am I going about this the wrong way? (note: this is a console project only, no GUI)
==========
code edited
I've changed the code to the above following the recommendations, and it works almost as I expect however the thread still doesnt seem to end properly. I was the while loop would die and control would eventually come back to the main method. Any ideas?
Because timesUP (please change the name!) is an inner class, it already has a reference to the instance of Boggle which created it. (That wouldn't be the case if it were marked as static.) If you wanted to create an instance of timesUP associated with another instance, you'd do something like:
otherBoggle.new timesUp();
It's pretty odd syntax, admittedly :)
This doesn't fix the problem that Midhat identified, admittedly - but it means you don't need to worry about getting a reference to the outer class. Just call endGame() from within timesUP.run() and it will call it on the appropriate instance.
You have blocking console input in the thread. The running time will be dictated by that. You can have the console input in a seperate thread, and add a timer in the current thread to kill the input thread after a minute, and call this.endGame()