Processing: running draw cycle into an independent thread - processing

QUESTION
I've noticed that draw() cycle is interrupted by events elaboration.
In the following example the circle animation will stop at mouse click until the elaborating_function() ends.
void setup(){
size(800, 600);
background(#818B95);
frameRate(30);
}
void draw(){
background(#818B95);
//simple animation
fill(0,116,217);
circle(circle_x, 200, 50);
circle_x += animation_speed;
if(circle_x>800){ circle_x = 0; }
}
void mouseClicked() {
elaborating_function();
}
void elaborating_function(){
println("elaboration start");
delay(1000);
println("elaboration end");
}
Of course, a simple solution to run the elaboration without stopping the animation could be to thread("elaborating_function");
But my question is: if it is possible to run the draw cycle into an independent thread instead?
SOLUTION
I've found a possible solution inverting my problem and creating an "independent cycle" parallel to the draw one. Within this cycle is possible to run any function and it will not interfere with the draw execution. Every event triggered by the user needs only to set a specific variable in order to activate (once or more time) the function within the cycle.
int circle_x = 0;
int animation_speed = 5;
boolean call_elaborating_function = false;
void setup(){
size(800, 600);
background(#818B95);
frameRate(30);
IndependentCycle independentCycle = new IndependentCycle();
independentCycle.setFrequency(1);
new Thread(independentCycle).start();
}
void draw(){
background(#818B95);
//simple animation
fill(0,116,217);
circle(circle_x, 200, 50);
circle_x += animation_speed;
if(circle_x>800){ circle_x = 0; }
}
public class IndependentCycle implements Runnable{
private int frequency; //execution per seconds
public IndependentCycle(){
frequency = 0;
}
public void setFrequency(int frequency){
this.frequency = 1000/frequency;
println(this.frequency);
}
public void run(){
while(true){
print(".");
delay(this.frequency);
//DO STUFF HERE
//WITH IF EVENT == ture IN ORDER TO RUN JUST ONCE !!
if(call_elaborating_function){
call_elaborating_function = false;
elaborating_function();
}
}
}
}
void mouseClicked() {
call_elaborating_function = true;
}
void elaborating_function(){
println("elaboration start");
delay(1000);
println("elaboration end");
}

As far as I know Processing has it's own AnimationThread.
Your proposed solution to thread elaborating_function() is great.
You could have a basic class that implements Runnable if you need a bit more control. With this thread running in parallel, Processing's main animation thread should run along side it just fine without pausing rendering.
This options sounds much simpler than trying to mess with Processing's AnimationThread and potentially have to deal with unexpected behaviour.
What is the actual goal you're trying achieve ?

Related

Is there a proper way to make a two distincts states program in processing?

For a project, I need to do a processing code able to switch between two completely different states. There is a default state and it switches to the special state when the mouse is pressed. The special state have an initialization phase. It also have an end and when it reaches it, the program switches back to the normal state. The way I would implement this is the following :
boolean isNormal;
void setup(){
//setup things...
isNormal = true;
}
void draw(){
if(isNormal){
normal();
}
else{
special();
if (endReached){
isNormal = true;
}
}
}
void mousePressed(){
specialSetup();
isNormal = false;
}
void normal(){
//normal routine...
}
void special(){
//special routine...
}
Is there a better way to do it (more efficient, cleaner, ...) ?

How can you disable the trun off screen mode in Processing 3?

I just want my computer's screen not to turn off while a program is runnig. I know I can set it on my PC settings but I just want this app to do it.
Can anybody help me?
Thanks!
I found the following code here
import java.awt.Robot;
import java.awt.MouseInfo;
long robotLastMove = 0;
Robot robot=null;
setup(){
try{
robot = new Robot();
}catch(Exception e){e.printStackTrace();}
}
draw(){
long now = System.currentTimeMillis();
if(robot!=null && now-robotLastMove>1000*60*15){
//TODO: move back the mouse
int x = MouseInfo.getPointerInfo().getLocation().x;
int y = MouseInfo.getPointerInfo().getLocation().y;
//robot.
robot.mouseMove(x+2, y+2);
robot.mouseMove(x, y);
robotLastMove=now;
}
}
This moves the mouse automatically when your PC tries to sleep, but only a little. If you save the code inside the draw function from the above code into a different function, you can call it in the the draw to make the code look better. Like this:
import java.awt.Robot;
import java.awt.MouseInfo;
long robotLastMove = 0;
Robot robot=null;
setup(){
try{
robot = new Robot();
}catch(Exception e){e.printStackTrace();}
}
void stayAwake(){
long now = System.currentTimeMillis();
if(robot!=null && now-robotLastMove>1000*60*15){
//TODO: move back the mouse
int x = MouseInfo.getPointerInfo().getLocation().x;
int y = MouseInfo.getPointerInfo().getLocation().y;
//robot.
robot.mouseMove(x+2, y+2);
robot.mouseMove(x, y);
robotLastMove=now;
}
}
void draw(){
background(0);
stayAwake();
// the code you want to run without your pc falling asleep.
}
Good luck!

does setup and draw function run parallel in processing

Does the fileselected function in this code complete its execution even before while loop execution?
void setup()
{
size(800, 600);
selectInput("Select a file to process:", "fileSelected");
while(data==null)
{
delay(1000);
}
}
void fileselected()
{
*
*
*
*
}
How do I make the draw function wait until it receives the necessary arguments to run?
does setup and draw function run parallel in processing
No. First the setup() function is called and completes, then the draw() function is called 60 times per second.
does the fileselected function completes its execution even before while loop execution.
The fileSelected() function will be called when the user selects a file. You really shouldn't call the delay() function in a loop like that.
How do I make the draw function to wait until it receives the necessary arguments to run.
Something like this:
boolean fileLoaded = false;
void setup(){
size(800, 600);
selectInput("Select a file to process:", "fileSelected");
}
void fileSelected(File selection){
fileLoaded = true;
}
void draw(){
if(!fileLoaded){
//short-circuit and stop the function
return;
}
}
You could go a step further and use the noLoop() and loop() functions. More info can be found in the reference.

Create more than one window of a single sketch in Processing

How to create more than one window of a single sketch in Processing?
Actually I want to detect and track a particular color (through webcam) in one window and display the detected co-ordinates as a point in another window.Till now I'm able to display the points in the same window where detecting it.But I want to split it into two different windows.
You need to create a new frame and a new PApplet... here's a sample sketch:
import javax.swing.*;
SecondApplet s;
void setup() {
size(640, 480);
PFrame f = new PFrame(width, height);
frame.setTitle("first window");
f.setTitle("second window");
fill(0);
}
void draw() {
background(255);
ellipse(mouseX, mouseY, 10, 10);
s.setGhostCursor(mouseX, mouseY);
}
public class PFrame extends JFrame {
public PFrame(int width, int height) {
setBounds(100, 100, width, height);
s = new SecondApplet();
add(s);
s.init();
show();
}
}
public class SecondApplet extends PApplet {
int ghostX, ghostY;
public void setup() {
background(0);
noStroke();
}
public void draw() {
background(50);
fill(255);
ellipse(mouseX, mouseY, 10, 10);
fill(0);
ellipse(ghostX, ghostY, 10, 10);
}
public void setGhostCursor(int ghostX, int ghostY) {
this.ghostX = ghostX;
this.ghostY = ghostY;
}
}
One option might be to create a sketch twice the size of your original window and just offset the detected coordinates by half the sketch's size.
Here's a very rough code snippet (assumming blob will be a detected color blob):
int camWidth = 320;
int camHeight = 240;
Capture cam;
void setup(){
size(camWidth * 2,camHeight);
//init cam/opencv/etc.
}
void draw(){
//update cam and get data
image(cam,0,0);
//draw
rect(camWidth+blob.x,blob.y,blob.width,blob.height);
}
To be honest, it might be easier to overlay the tracked information. For example, if you're doing color tracking, just display the outlines of the bounding box of the tracked area.
If you really really want to display another window, you can use a JPanel.
Have a look at this answer for a running code example.
I would recommend using G4P, a GUI library for Processing that has some functionality built in for handling multiple windows. I have used this before with a webcam and it worked well. It comes with a GWindow object that will spawn a window easily. There is a short tutorial on the website that explains the basics.
I've included some old code that I have that will show you the basic idea. What is happening in the code is that I make two GWindows and send them each a PImage to display: one gets a webcam image and the other an effected image. The way you do this is to augment the GWinData object to also include the data you would like to pass to the windows. Instead of making one specific object for each window I just made one object with the two PImages in it. Each GWindow gets its own draw loop (at the bottom of the example) where it loads the PImage from the overridden GWinData object and displays it. In the main draw loop I read the webcam and then process it to create the two images and then store them into the GWinData object.
Hopefully that gives you enough to get started.
import guicomponents.*;
import processing.video.*;
private GWindow window;
private GWindow window2;
Capture video;
PImage sorted;
PImage imgdif; // image with pixel thresholding
MyWinData data;
void setup(){
size(640, 480,P2D); // Change size to 320 x 240 if too slow at 640 x 480
// Uses the default video input, see the reference if this causes an error
video = new Capture(this, 640, 480, 24);
numPixels = video.width * video.height;
data = new MyWinData();
window = new GWindow(this, "TEST", 0,0, 640,480, true, P2D);
window.isAlwaysOnTop();
window.addData(data);
window.addDrawHandler(this, "Window1draw");
window2 = new GWindow(this, "TEST", 640,0 , 640,480, true, P2D);
window2.isAlwaysOnTop();
window2.addData(data);
window2.addDrawHandler(this, "Window2draw");
loadColors("64rev.csv");
colorlength = mycolors.length;
distances = new float[colorlength];
noCursor();
}
void draw()
{
if (video.available())
{
background(0);
video.read();
image(video,0,0);
loadPixels();
imgdif = get(); // clones the last image drawn to the screen v1.1
sorted = get();
/// Removed a lot of code here that did the processing
// hand data to our data class to pass to other windows
data.sortedimage = sorted;
data.difimage = imgdif;
}
}
class MyWinData extends GWinData {
public PImage sortedimage;
public PImage difimage;
MyWinData(){
sortedimage = createImage(640,480,RGB);
difimage = createImage(640,480,RGB);
}
}
public void Window1draw(GWinApplet a, GWinData d){
MyWinData data = (MyWinData) d;
a.image(data.sortedimage, 0,0);
}
public void Window2draw(GWinApplet a, GWinData d){
MyWinData data = (MyWinData) d;
a.image(data.difimage,0,0);
}

Closing stage after specific event

How do I close a stage in JavaFX 2 after some specific external event has occurred? Suppose I have a stage with a simple progress bar that is filled up by a Task (borrowed from another answer):
Task<Void> task = new Task<Void>(){
#Override
public Void call(){
for (int i = 1; i < 10; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i);
updateProgress(i, 10);
}
return null;
}
};
How do I close the window automatically (and open the next one) after the Task is done and the ProgressBar is filled to 100%?
Before return null; you can add
Platform.runLater(
new Runnable() {
public void run() {
stage.close();
}
}
);
or
progressBar.progressProperty().addListener(new ChangeListener<Number>(){
//add checking, that progress is >= 1.0 - epsilon
//and call stage.close();
})
The first is better. But note, that task is done on a separate thread. so you should put a request on stage.close() on JFX thread using special call.
Also, jewelsea provides links on stage closing questions in comment to the question.

Resources