selectInput() not opening file dialogue when used as intended

Hello. I am on a Macbook running macOS Monterey 12.0.1 and I found an issue (or a mistake I wasn’t able to solve) with selectInput() in Processing. My goal was to use it to pass an image to the program which I then do what I wanted to do with, and then save the result into the project folder for me to look at.

I looked up the documentation for it and it had this example:

void setup() {
  selectInput("Select a file to process:", "fileSelected");
}

void fileSelected(File selection) {
  if (selection == null) {
    println("Window was closed or the user hit cancel.");
  } else {
    println("User selected " + selection.getAbsolutePath());
  }
}

I altered the line in the else statement to just set a PImage variable p as the output of the function loadImage() with selection.getAbsolutePath() as the input (for me to then use in draw()), like this:

PImage p;

void setup() {
  selectInput("Select a file to process:", "fileSelected");
}

void fileSelected(File selection) {
  if (selection == null) {
    println("Window was closed or the user hit cancel.");
  } else {
    p = loadImage(selection.getAbsolutePath());
  }
}

void draw() {
  //the code I manipulated p with
}

The theory is I run this, the file dialogue opens, I choose a file, it gets passed to fileSelected where the file is put in the p variable for me to then use. However, when I run it, the dialogue doesn’t open, inputFile() sends null to the fileSelected() function where it is put into p and the code in draw() throws a nullPointerException. Also worth noting that the first example (the code I found in the documentation) also had this issue and always printed null and the dialogue box wouldn’t show up.

Strangely enough, if I add a while loop in the draw() function that prints something every cycle, the dialogue pops up and the program works normally, like this:

void draw() {
    
  while (p==null) {
    println("waiting for image");
  }
  
  //other code cut out

}

This doesn’t work, however, if the while loop has nothing in it (like while(p==null){} ).

My theory is that the program doesn’t stop for the dialogue to find the image, but adding the while loop ‘distracts’ it for the dialogue to pop up and the user to select an image, which is put into the p variable and thus stops the loop and the program can continue normally. The documentation also says: “The callback is necessary because of how threading works”, which might support my theory (main thread running draw() doesn’t wait for thread running selectInput() to get a file).

Is there some monumental mistake I made here? This doesn’t feel like it’s bugged and I found a workaround. I feel like I’m missing something. Any help is appreciated because I feel as if having a while loop there only to pad for time is pretty bad design. Thanks

EDIT: After testing my solution a little bit I found out after a few runs it stops working and doesn’t go past the loop (similar to the behavior if I just left the loop empty instead of printing something) and I have to restart Processing to get it to work again. This solution screams janky so I’m just going to remove it until I hopefully find a solution

If this IS a bug, then I have to assume it’s because the “waiting for additional input” the documentation claims that the program is doing isn’t actually happening and continues running while inputFile() is still either opening the dialogue box or waiting for user input, until the main thread/program reaches the draw() function almost instantly and runs the first line of code using p and crashes since it’s still null.

I am not well versed in threads, so this is probably wrong, but I figure something along these lines is happening (of course, if I hadn’t made any mistakes to begin with).

here

(maybe it’s your missing size() command or something)


int state=0; 
PImage p;

void setup() {
  size(560, 560);
}

void draw() {
  //
  background(0);

  if (state==0) {
    state=1;
    selectInput("Select a file to process:", "fileSelected");
  } else if (state==1) {
    // wait
  } else if (state==2) {
    image(p, 0, 0);
  }
}

//------------------------------------------------------------

void fileSelected(File selection) {
  if (selection == null) {
    println("Window was closed or the user hit cancel.");
  } else {
    p = loadImage(selection.getAbsolutePath());
    state=2;
  }
}

I didn’t mention this in the original post but I have noloop() in the setup, since I only need draw() to run once (get picture, alter it, put result in project folder). From the looks of it this solution only works if draw() is looped. Sorry about that

You can add your noLoop () after
the lines that store the altered image

OR reset state to 0

All of Processing’s select???(…) methods are executed on a separate thread. It means that the first time draw() is executed happens before the fileSelected(…) method. So if you want to process the file in draw() then you should not use noLoop().

Try this sketch out it shows what I mean

PImage p;

void setup() {
  selectInput("Select a file to process:", "fileSelected");
}

void fileSelected(File selection) {
  if (selection == null) {
    println("Window was closed or the user hit cancel.");
  } else {
    p = loadImage(selection.getAbsolutePath());
  }
}

void draw() {
  background(255);
  if (p != null) {
    // Never executed
    println("Processing image");
  } else {
    println("NO IMAGE");
  }
  noLoop();  // Try again without this line
}
1 Like

I would never make a Sketch without size()

1 Like