How to make a condition of two fields?

642 Views Asked by At

Good afternoon, I need to add several conditions to validate two fields in the current code.

  1. The Min field must not exceed the Max field. Min <Max / 5000 <4000 prohibited when entering.
  2. The Max field must not be less than the Min field. Max <Min / 4000 <5000 prohibited when entering.
  3. The Min field should not exceed the interval from the Max field, 500 units less can be entered. For instance: Min 4500 and Max 5000, 4400/5000, 4250/5000, 4501/5000 are prohibited to enter and above.
  4. The Min and Max fields must not be equal. Min = Max is prohibited when entering.

enter image description here enter image description hereenter image description here

code:

import controlP5.*;

ControlP5 cp5;
Textfield O;
Textfield OO;

void setup() {
  size(700, 400);

  PFont font = createFont("arial", 18);

  cp5 = new ControlP5(this);

  O = cp5.addTextfield("MIN")
    .setPosition(20, 100)
    .setSize(200, 40);
  O.setInputFilter(ControlP5.INTEGER)
    .setFont(font)
    .setColor(color(255, 0, 0));

  OO = cp5.addTextfield("MAX")
    .setPosition(20, 170)
    .setSize(200, 40);
  OO.setInputFilter(ControlP5.INTEGER)
    .setFont(font);

  textFont(font);
}

void draw() {
  if (keyPressed && OO.isFocus()) {
    float n;
    try {
      n = Float.parseFloat(OO.getText().replace(',', '.'));
      if (!(n >= 1 && n <= 12000)) {
        throw new NumberFormatException(); // throw to catch below
      }
    } 
    catch (Exception e2) {
      String t;
      if (OO.getText().length() > 1) {
        t = OO.getText().substring(0, OO.getText().length() - 1);
      } else {
        t = "";
      }
      OO.setText(t);
    }
  }
  if (keyPressed && O.isFocus()) {
    float n;
    try {
      n = Float.parseFloat(O.getText().replace(',', '.'));
      if (!(n >= 1 && n <= 11500)) {
        throw new NumberFormatException(); // throw to catch below
      }
    } 
    catch (Exception e2) {
      String t;
      if (O.getText().length() > 1) {
        t = O.getText().substring(0, O.getText().length() - 1);
      } else {
        t = "";
      }
      O.setText(t);
    }
  }
  background(0);
  fill(255);
}
1

There are 1 best solutions below

2
On BEST ANSWER

Overall it sounds like you're trying to have the user enter a range of valid values (where the minimum is always smaller than the maximum). There's already a ControlP5 controller for that: Range

Other than allowing to set a min and max value within a range is the constraint to keep a difference between max and min value of at least 500.

You could get away with making the Range slider handles 0px wide, essentially disabling them which means the range you set at the start (via setRangeValues) will be maintained:

import controlP5.*;

ControlP5 cp5;

Range range;

int rangeMinValue;
int rangeMaxValue;

void setup() {
  size(700, 400);

  PFont font = createFont("arial", 18);

  cp5 = new ControlP5(this);

  range = cp5.addRange("yourRange")
             // disable broadcasting since setRange and setRangeValues will trigger an event
             .setBroadcast(false) 
             .setFont(font)
             .setPosition(50,50)
             // notice the dimensions are proportional to the min/max range to avoid floating point values
             .setSize(500,40)
             // set minimum - maximum range here
             .setRange(4000,5000)
             // example: set initial (recommended) range values
             .setRangeValues(4000, 4500)
             // workaround to disable left/right handles contraining the range to 500
             .setHandleSize(0)
             // after the initialization we turn broadcast back on again
             .setBroadcast(true)
             ;
  
  textFont(font);
}

void draw() {
  background(0);
  fill(255);
}

void controlEvent(ControlEvent event) {
  if(event.isFrom("yourRange")) {
    // min and max values are stored in an array.
    // access this array with controller().arrayValue().
    // min is at index 0, max is at index 1.
    rangeMinValue = int(event.getController().getArrayValue(0));
    rangeMaxValue = int(event.getController().getArrayValue(1));
    println("range:",rangeMinValue,"->",rangeMaxValue);
  }
  
}

range sliders: contrained range size

The one limitation is that ranges can't be > 500. If that's a requirment, you can still manually constrain the values (by setting the range min(low)/max(high) values):

import controlP5.*;

// range constants
final int RANGE_MIN = 4000;
final int RANGE_MAX = 5000;
// the smallest allowed difference between min/max values
final int RANGE_MIN_DIFFERENCE = 500;
final int RANGE_MID = RANGE_MIN + ((RANGE_MAX - RANGE_MIN) / 2);

ControlP5 cp5;

Range range;

int rangeMinValue;
int rangeMaxValue;

void setup() {
  size(700, 400);

  PFont font = createFont("arial", 18);

  cp5 = new ControlP5(this);

  range = cp5.addRange("yourCustomRange")
             // disable broadcasting since setRange and setRangeValues will trigger an event
             .setBroadcast(false) 
             .setFont(font)
             .setPosition(50,50)
             // notice the dimensions are proportional to the min/max range to avoid floating point values
             .setSize(500,40)
             // set minimum - maximum range here
             .setRange(RANGE_MIN, RANGE_MAX)
             // example: set initial (recommended) range values
             .setRangeValues(RANGE_MIN, RANGE_MIN + RANGE_MIN_DIFFERENCE)
             // after the initialization we turn broadcast back on again
             .setBroadcast(true)
             ;
  
  textFont(font);
}

void draw() {
  background(0);
  fill(255);
}

void controlEvent(ControlEvent event) {
  if(event.isFrom("yourCustomRange")) {
    // min and max values are stored in an array.
    // access this array with controller().arrayValue().
    // min is at index 0, max is at index 1.
    int rangeMinInt  = int(event.getController().getArrayValue(0));
    int rangeMaxInt  = int(event.getController().getArrayValue(1));
    // if the values are within the desired range, update global values
    if(rangeMaxInt - rangeMinInt >= RANGE_MIN_DIFFERENCE){
      rangeMinValue = rangeMinInt;
      rangeMaxValue = rangeMaxInt;
    }else{
      // otherwise check which side of the range should be constrained (right/max) or (left/min) to overwrite user input
      if(rangeMaxInt > RANGE_MID){
        range.setLowValue(rangeMaxInt - RANGE_MIN_DIFFERENCE);
      }else{
        range.setHighValue(rangeMinInt + RANGE_MIN_DIFFERENCE);
      }
    }
    // values to use
    println("range:",rangeMinValue,"->",rangeMaxValue);
  }
  
}

Range sliders: editable range constrained

If that takes too much space you can use Numberbox which compared to the text field has a few advantages:

  • you don't need to worry about string to integer conversion (it handles numbers by default)
  • you can set min/max values

Here's an example:

import controlP5.*;

ControlP5 cp5;

// range constants
final int RANGE_MIN = 4000;
final int RANGE_MAX = 5000;
// the smallest allowed difference between min/max values
final int RANGE_MIN_DIFFERENCE = 500;
final int RANGE_MID = RANGE_MIN + ((RANGE_MAX - RANGE_MIN) / 2);

int minValue;
int maxValue;

Numberbox inputMin;
Numberbox inputMax;

void setup() {
  size(700, 400);

  PFont font = createFont("arial", 18);

  cp5 = new ControlP5(this);

  inputMin = cp5.addNumberbox("minValue")
             .setPosition(100,100)
             .setSize(100,20)
             .setFont(font)
             .setScrollSensitivity(1.1)
             // set initial acceptable range
             .setMin(RANGE_MIN)
             .setMax(RANGE_MAX)
             // set default value
             .setValue(4000)
             ;
  
  inputMax = cp5.addNumberbox("maxValue")
             .setPosition(100,150)
             .setSize(100,20)
             .setFont(font)
             .setScrollSensitivity(1.1)
             // set initial acceptable range
             .setMin(RANGE_MIN)
             .setMax(RANGE_MAX)
             // set default value
             .setValue(RANGE_MID + 1)
             ;
  
  
  textFont(font);
}

void draw() {
  constrainRangeInputs();
  background(0);
  fill(255);
  text("minValue: " + minValue + "\n" +
       "maxValue: " + maxValue, 10, 15);
}

void constrainRangeInputs(){
  int rangeMinInt = (int)inputMin.getValue();
  int rangeMaxInt = (int)inputMax.getValue();
  // 
  if(abs(rangeMaxInt - rangeMinInt) < RANGE_MIN_DIFFERENCE){
    if(rangeMaxInt > RANGE_MID){
      inputMin.setValue(rangeMaxInt - RANGE_MIN_DIFFERENCE);
    }else{
      inputMax.setValue(rangeMinInt + RANGE_MIN_DIFFERENCE);
    }
  }
}

range number boxes

The logic constrain values to a minimum 500 difference is not 100% tight, there may some other edge cases I haven't considered. It's more of a way to illustrate ways of solving the problem so you're better equipt to do so.

I would recommend going through Processing > Examples > Contributed Libraries > ControlP5 and running the examples, in particular the controllers. You can prioritise the ones that sound closer to your current problem, but it's worth getting experience with the options so you can choose the best controllers/UI element to fit your problem.

The example may not include usage of every method the controller has, however there's a comment list at the bottom you could easily copy/paste/run immediately. Additionally of course you have the full documentation