Search code examples
javaprocessingcontrol-p5

How do I make the conditions of the data in the textbox two fields meet?


Good afternoon, I was already prompted how this can be done with cp5.addNumberbox, but I tried different options and still could not beat cp5.addTextfield. Nothing works! The tasks were as follows: 1). The minValue field must not exceed the MaxValue field when entering numbers. 2). The MaxValue field must not be less than the minValue field when entering numbers. 3). The minValue field must not exceed the range from the maxValue field by 500 units. I post the simplest version of the code without my fanaticism: enter image description here

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;

Textfield inputMin;
Textfield inputMax;

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

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

  cp5 = new ControlP5(this);

  inputMin = cp5.addTextfield("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.addTextfield("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);
    }
  }
}

Solution

  • The way you phrased the question sounds like you're giving instructions to someone else to do your work for you. Although you've stated your goals, you have not stated:

    • what is the problem you're experiencing ("Nothing works! " doesn't say anything to anybody trying to help you)
    • what have you tried to resolve the issue (what the expected behaviour is and what the actual behaviour is)

    I've ran your code and after typing into a field I get this error:

    java.lang.IllegalArgumentException: Can not set int field sketch_201009b.minValue to java.lang.String
        at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
        at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
        at sun.reflect.UnsafeIntegerFieldAccessorImpl.set(UnsafeIntegerFieldAccessorImpl.java:98)
        at java.lang.reflect.Field.set(Field.java:764)
        at controlP5.ControlBroadcaster.invokeField(Unknown Source)
        at controlP5.ControlBroadcaster.callTarget(Unknown Source)
        at controlP5.ControlBroadcaster.broadcast(Unknown Source)
        at controlP5.Controller.broadcast(Unknown Source)
        at controlP5.Controller.broadcast(Unknown Source)
        at controlP5.Textfield$Enter.execute(Unknown Source)
        at controlP5.Textfield.keyEvent(Unknown Source)
        at controlP5.ControllerGroup.keyEvent(Unknown Source)
        at controlP5.ControlWindow.handleKeyEvent(Unknown Source)
        at controlP5.ControlWindow.keyEvent(Unknown Source)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at processing.core.PApplet$RegisteredMethods.handle(PApplet.java:1411)
        at processing.core.PApplet.handleMethods(PApplet.java:1613)
        at processing.core.PApplet.handleKeyEvent(PApplet.java:2949)
        at processing.core.PApplet.dequeueEvents(PApplet.java:2602)
        at processing.core.PApplet.handleDraw(PApplet.java:2440)
        at processing.awt.PSurfaceAWT$12.callDraw(PSurfaceAWT.java:1557)
        at processing.core.PSurfaceNone$AnimationThread.run(PSurfaceNone.java:313)
    

    I will assume this is your problem.

    It appears you have simply replaced the Numberbox components from the 3rd example in this answer with TextField however it appears you have not paid attention to the differences between components:

    • Numberbox works with numbers
    • TextField works with text

    As previously mentioned, there's ample ControlP5 documentation (as well as examples). Learn how to use documentation (here's an example video, same applies to java/Processing/any other language/library with documentation) and use it.

    The least you could try is something like:

    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;
    String minValueString;
    String maxValueString;
    
    Textfield inputMin;
    Textfield inputMax;
    
    void setup() {
      size(700, 400);
    
      PFont font = createFont("arial", 18);
    
      cp5 = new ControlP5(this);
    
      inputMin = cp5.addTextfield("minValueString")
        .setPosition(100, 100)
        .setSize(100, 20)
        .setFont(font)
        ;
    
      inputMax = cp5.addTextfield("maxValueString")
        .setPosition(100, 150)
        .setSize(100, 20)
        .setFont(font)
        ;
    
    
      textFont(font);
    }
    
    void draw() {
      constrainRangeInputs();
      background(0);
      fill(255);
      text("minValue: " + minValue + "\n" +
           "maxValue: " + maxValue, 10, 15);
    }
    
    void constrainRangeInputs() {
      int rangeMinInt = int(inputMin.getText());
      int rangeMaxInt = int(inputMax.getText());
      // 
      if (abs(rangeMaxInt - rangeMinInt) < RANGE_MIN_DIFFERENCE) {
        if (rangeMaxInt > RANGE_MID) {
          inputMin.setText((rangeMaxInt - RANGE_MIN_DIFFERENCE) + "");
        } else {
          inputMax.setText((rangeMinInt + RANGE_MIN_DIFFERENCE) + "");
        }
      }
    }
    

    Notice this part:

    inputMin = cp5.addTextfield("minValueString")
    inputMax = cp5.addTextfield("maxValueString")
    

    This is what caused the error previously. ControlP5 would've attempted to map minValue from the Numberbox component name to the sketch's int minValue; property at the top, however it's handling a String now (as it's a TextField), not an int (like Numberbox does)

    Also handling String to int:

      int rangeMinInt = int(inputMin.getText());
      int rangeMaxInt = int(inputMax.getText());
    

    Personally, I can not recommend going on this inefficient and error prone path or converting back and forth between String and integers making for a very awkward user experience entering data. You're on your own in terms of handling String text input to integer value within 4000 / 5000 range, etc.

    This seems related to your questions from August onwards when I have suggested using better suited UI elements and data handling (like Numberbox) instead of TextField. Additionally I have also made suggestions regarding text formatting, naming variables, using documentation, etc. however they appear to have been dismissed.

    I get that programming at the beginning can get frustrating when things don't work, but these are opportunities to slow down, learn how to debug, understand the problem in detail and try again. A program will probably not do what you want it to do, but what you tell it to do. Somewhere in there there must be a simple explanation and solution to move forward (to the next problem, until the program works as expected). You will learn a lot more when things go wrong and you fix them as opposed to situations when things just work, but you don't know why.