javajavafxkeyboard-shortcutsrunnable

Create Runnable with "final" variable from the parent?


Create multiple new Runnable inside a loop ?

I want to create multiple new instances of Runnable that calls another method and passing the "i" parameter from the parent's loop.

I do not want to use Threads since those runnables will be used as actions for keyboard shortcuts (using KeyCombination and accelerators). (ex: Ctrl + 1, Ctrl + 2, ... Ctrl + 9)

The content of the runnable that I want looks like this :

if (shortcutsEnabled && checkDestinationValidity(i)) {
    copyImage(i);
}

possibly important : the number of "i" will go up to 9.

Is there any way to do this without having to make a premade table of Runnable ?

When I try to just put the variable inside, the NetBeans IDE shows me this message : local variables referenced from a lambda expression must be final or effectively final

I have found a solution that has delayed my "deadline" for the solution :

for (int i = 0; i < copyKeyCombinations.size(); i++) {
    final int index = i;
    Runnable copyRunnable = ()-> {
        if (shortcutsEnabled && checkDestinationValidity(index)) {
            copyImage(index);
        }
    };
    accelerators.put(copyKeyCombinations.get(i), copyRunnable);
}

For the record, the runnable are registered before the loop ends, and the solution above works but I was asked to find another solution

However, this is a solution that is not accepted for my work situation, I am looking for any alternatives.

(Note : this loop will only be launched one time, at the start of the app).


Solution

  • You can implement Runnable the "standard" way, as a class, not as lambda function:

    public class CopyRunnable implements Runnable {
    
      private final int index;
      private final boolean shortcutsEnabled;
    
      public CopyRunnable(int index, boolean shortcutsEnabled) {
        this.index = index;
        this.shortcutsEnabled = shortcutsEnabled;
      }
    
      @Override
      public void run() {
        if (shortcutsEnabled && checkDestinationValidity(index)) {
          copyImage(index);
        }
      }
    }
    
    for (int i = 0; i < copyKeyCombinations.size(); i++) {
      Runnable copyRunnable = new CopyRunnable(i, shortcutsEnabled);
      //do something with it
    }