So I want to check if nodes are in certain range and if so, draw them or not.
The nodes are checked inside a timer, so a thread is created. Only issue right now is that method setRenderable() have to be called from UI thread. So is there a way to bypass that ? I need this to update in certain interval that's why I create timer.
public void updateNodes()
{
Camera camera = arFragment.getArSceneView().getScene().getCamera();
timer = new Timer();
timer.schedule(new TimerTask(){
int last = 0;
int copy_last = 0;
#Override
public void run(){
Vector3 camera_position = camera.getWorldPosition();
// We're checking all nodes for distance between them
for(Node al : copied_nodes_list){
if(last<copy_last) last++;
else if(countDistanceOfNodes(al,camera_position)<3.0 && copy_last >= last) {
al.setRenderable(andyRenderable);
last++;
copy_last = last;
}
else {
al.setRenderable(andyRenderable);
}
}
last = 0;
}
},0,250);
}
Create a variable in your class.
Set the value when the object is initialized or write a setter against that variable.
Within the run function, check against the condition against that variable and write the business rules accordingly.
Okay, so there's function in android called runOnUiThread(); Which basically doing whats it's called. I attach the working code.
public void updateNodes()
{
Camera camera = arFragment.getArSceneView().getScene().getCamera();
Timer timer = new Timer();
timer.schedule(new TimerTask(){
int last = 0;
int copy_last = 0;
#Override
public void run(){
Vector3 camera_position = camera.getWorldPosition();
// We're checking all nodes for distance between them
for(Node al : copied_nodes_list){
camera_position = camera.getWorldPosition();
if(last<copy_last) last++;
else if(countDistanceOfNodes(al,camera_position)<3.0 && copy_last >= last) {
runOnUiThread(new Runnable(){
#Override
public void run(){
al.setRenderable(andyRenderable);
}
});
last++;
copy_last = last;
}
else {
runOnUiThread(new Runnable(){
#Override
public void run(){
al.setRenderable(null);
}
});
}
}
last = 0;
}
},0,100);
}
Related
Below is a peice of code where on click the player will make their move by placing the X counter and then the computer will make their move by placing a O counter. The
only issue with this code currently is that when the player places their X counter, the O counter is placed as well at the same time. So it looks like both the player
and the computer has made their moves at the same time and that happens everytime the player makes their move.
What I want to ask, is it possible to include like a 2 second time delay so that the player will place their X and then after 2 seconds the computer will place their O?
Thanks in advance
#Override
public void onClick(View v) {
if (!((Button) v).getText().toString().equals("")) {
return;
}
if (playerOneMove) {
((Button) v).setText("X");
((Button) v).setTextColor(playerX);
computerMove();
}
}
private void computerMove() {
String[][] field = new String[3][3];
Random random = new Random(); //you may want to declare this as a class field
List<Button> emptyButtons = new ArrayList<>();
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
field[i][j] = buttons[i][j].getText().toString();
if (field[i][j].equals("")) {
emptyButtons.add(buttons[i][j]);
}
}
}
Button selectButton;
for (int i = 0; i < 3; i++) {
if (field[i][0].equals(field[i][1])
&& field[i][2].equals("")){
//prevent win/win on rows by selecting the correct button here
}
else if (field[i][0].equals(field[i][2])
&& field[i][1].equals("")){
//prevent win/win on rows by selecting the correct button here
}
else if (field[i][1].equals(field[i][2])
&& field[i][0].equals("")){
//prevent win/win on rows by selecting the correct button here
}
else {
selectButton = emptyButtons.get(random.nextInt(emptyButtons.size()));
}
selectButton.setText("O");
selectButton.setTextColor(playerO);
}
You could put computer logic inside handler or timer task: How to call a method after a delay in Android
but you also need some flag, that will block user placing X while you are waiting for computer to make it move.
i edited your onclick with the delay and i think you gonna need some sort of the flag wich blocks user until computer makes the move !
#Override
public void onClick(View v) {
if (!((Button) v).getText().toString().equals("")) {
return;
}
if (playerOneMove) {
((Button) v).setText("X");
((Button) v).setTextColor(playerX);
//2000 is your delay in mills format
v.postDelayed(new Runnable() {
#Override
public void run() {
computerMove();
}
},2000)
}
}
and i think it would be good idea to use some random number between 1sec to 3sec for delay and not the constant delay it creates better experience for user
You can check out the Handler and Runnable class in android. You can delayed the time of a method as required.
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//Do something after 100ms
}
}, 100);
With the following code,the thread is activated on button click in the controller class. Thing is, I want to be able to change the values in he Line array, to have to anchor pane erase old lines and add new lines.This is in the controller.java after main in launched.
static startVal = -1,endVal = -1;
Lines L;//this is supposed to store new lines after some methods are called
//this method is called on button click and I want it to start again every time the button is clicked
public void drawPath(){
Task task = new Task<Void>() {
#Override
public Void call() throws Exception {
while(true){
int i = 0;
while (i<5) {
final int finalI = i;
Platform.runLater(new Runnable() {
#Override
public void run() {
anchPane.getChildren().add(L[finalI]);
if(startVal == -1)
startVal = anchPane.getChildren.size()-1;
else
endVal = anchPane.getChildren().size()-1;
}
});
i++;
Thread.sleep(2000);
}
//removeLines();
anchPane.getChildren().remove(startVal,endVal);
}
}
};
Thread th = new Thread(task);
th.setDaemon(true);
th.start();
}
I am making this program where i let the person set up a workout in form of running intervals. I have made a timer that i want to work as the "sleeptime" for the loop but for some reason it only gets the first value almost as if when you set the value it locks to that value. The values of the timelapse are set up in a menu of JSliders.
public static ArrayList <JSlider> sliderList = new ArrayList<JSlider>();
public static ArrayList <Integer> timeLapse = new ArrayList<Integer>();
buttonList.get(2).addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
frame.getContentPane().removeAll();
if(sliderList.size() > 1){
for(int i = 0; i < sliderList.size();i++){
timeLapse.add(sliderList.get(i).getValue());
}
Timer timer = new Timer();
timer.schedule(new TimerTask()
{
public void run() {
if(currentColor == Color.red){
currentColor = Color.green;
timeLapseCounter++;
music(startSound);
green.setIcon(new ImageIcon(("green.jpg")));
green.setBounds(0,0,WIDTH,HEIGHT);
frame.getContentPane().remove(red);
frame.getContentPane().add(green);
game.repaint();
}else if(currentColor == Color.green){
currentColor = Color.red;
timeLapseCounter++;
red.setIcon(new ImageIcon("red.jpg"));
red.setBounds(0,0,WIDTH,HEIGHT);
frame.getContentPane().remove(green);
frame.getContentPane().add(red);
music(stopSound);
game.repaint();
}
}
},0, timeLapse.get(timeLapseCounter));
timeLapse.clear();
}
}
});
I'm just trying to change the color of my drawn circle with a timer. I have implemented following code into my "onCreate" method:
Timer t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
Drawing.switchColor();
}
});
}
},
1000,
1000);
The method switchColor() does the following action:
public static void switchColor() {
Random r = new Random(30);
int random = r.nextInt();
if(random < 10) {
p.setColor(Color.GREEN);
}
else if(random >10 && random < 20) {
p.setColor(Color.BLUE);
}
else {
p.setColor(Color.RED);
}
}
When I run this, the color stays at it's default.
Does anyone know whether I have to use a handler within or a different timer model?
Thanks in advance!
I now found a suitable solution:
//-------------------Part 1 of AddCircleTimer------------------------
//Declare the timerAddCircle
timerAddCircle = new Timer();
timerAddCircle.schedule(new TimerTask() {
#Override
public void run() {
TimerMethodAddCircle();
}
}, 1000, 1000);
//-------------------Part 2 of AddCircleTimer------------------------
private void TimerMethodAddCircle()
{
//This method is called directly by the timer and runs in the same thread as the timer.
//We call the method that will work with the UI through the runOnUiThread method.
this.runOnUiThread(Timer_Add);
}
private Runnable Timer_Add = new Runnable() {
public void run() {
//This method runs in the same thread as the UI.
//Do something to the UI thread here
Drawing.addCircle();
d.invalidate();
}
};
//-------------------END Part 2 of AddCircleTimer------------------------
This works very fine and I can use it for even more timers and different methods!
Thanks to all!
Your t.start() is missing, either in onCreate, onStart, or onResume, depending on when you want to start your timer.
How can I make an android app that generates a random word every 1 second?
Here is my code:
new Timer().scheduleAtFixedRate(new TimerTask(){
public void run()
{
started = true;
word = "";
for (int i = 0; i < lenght+1; i++)
{
int j = rand.nextInt((max-min) + 1) + min;
word += tr.Translate(j);
}
txt.setText(word);
}
}, 0, 5000);
It seems that my app stops every time it must change the text of the TextView("txt"); how can I make this work?
Undoubtfully, run this within a Thread. Doing this, it will generate the words in background and once it already has, the main UI thread must just append the content to the txt instance.
new Thread(
new Runnable() {
public void run() {
// your stuff
}
}
).start()
To assign the result to the txt object, you'll probably be unable to do it within this thread. To do so, you'll need to declare a Handler in your Activity and use that handler within your thread, so it uses sendMessage() to the main Activity and the Activity just sets the text.
More on this here and here.
---- EDIT ----
As #FD_ says, there is another way to do the update without the use of a Handler. You would just need to call the runOnUiThread() method, something like this:
runOnUiThread(new Runnable() {
public void run() {
txt.setText(your_new_text);
}
});
Another way is using an AsyncTask, which is (talking vaguely) an "evolution" of a thread which makes a lot of stuff for you. More on AsyncTasks here.
---- EDIT ----
This would be one of the ways:
new Thread(
new Runnable() {
public void run() {
new Timer().scheduleAtFixedRate(new TimerTask() {
public void run() {
started = true;
word = "";
for (int i = 0; i < lenght+1; i++)
{
int j = rand.nextInt((max-min) + 1) + min;
word += tr.Translate(j);
}
// This will update your txt instance without the need of a Handler
runOnUiThread(new Runnable() {
public void run() {
txt.setText(word);
}
});
}
}, 0, 5000);
}
}).start();
try this:
int i = 0;
public void changeString() {
started = true;
word = "";
int j = rand.nextInt((max - min) + 1) + min;
word += tr.Translate(j);
txt.setText(word);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if (i < lenght + 1) {
changeString();
i++;
}
}
}, 1000);
}
You can do this using timer as well
int i=0;
new Timer().scheduleAtFixedRate(new TimerTask(){
public void run()
{
started = true;
word = "";
int j = rand.nextInt((max-min) + 1) + min;
word += tr.Translate(j);
txt.setText(word);
i++
}
}, 0, 5000);
try the above. The mistake you were making is using a for loop inside run instead use loop run method it-self.