ControlP5 control labeling "Examples" automatic, mine not there

edited July 2017 in Library Questions

Learning ControlP5 a bit painful but that's OK except for occasional puzzles such as:

In CP5 examples the creation of a toggle control is this:

      cp5.addToggle("toggle")
         .setPosition(40,250)
         .setSize(50,20)
         .setValue(true)
         .setMode(ControlP5.SWITCH)
         ;

This generates not only the default coloration (black/blue) but places the "toggle" characters in all-caps below the graphic. My nearly-identical code is this:

    cp5.addToggle("run-pause")
       .setPosition(900, 50)
       .setSize(50, 40)
       .setValue(true)
       .setMode(ControlP5.SWITCH)
       ;

It creates the expected blue/black widget but no "RUN-PAUSE" text below the control. Why? Sure, I can add a text label and would do so to provide better captions for certain controls but it's still a puzzle.

Answers

  • Further: I've found the additional parameter ".setCaptionLabel("text")" and I can initialize the text under the toggle graphic to "Running" -- although I'm not fond of all-caps. The next step is the event handler to respond to the toggle click: change Running to Paused while issuing the appropriate loop() or noLoop() commands. (I'm interrupting the draw() cycle.)

    That is, what goes into the annotated lines below?

    public void runPause(boolean theFlag) {
        if (theFlag == true) {
            loop();
            //setCaptionLabel("Running");
        } else {
            noLoop();
            //setCaptionLabel("Paused");
        }
    }
    

    I know I'm confused as to what object the setCaptionLabel() method is attached. But a couple of wild guesses haven't worked.

  • OK, fixed it myself. Created Toggle variable and set it to the Toggle returned from the cp5.addToggle("runPause") call during setup(). This in setup():

        RunPauseToggle = cp5.addToggle("runPause")
           .setPosition(ctrlOffsetX, ctrlOffsetY)
           .setSize(100, ctrlSizeY)
           .setFont(font)
           .setCaptionLabel("Running")
           .setColorCaptionLabel(0)
           .setValue(true)
           .setMode(ControlP5.SWITCH)
           ;
    

    The code (outside the draw() loop) associated with the toggle widget is this:

    public void runPause(boolean theFlag) {
        if (theFlag == true) {
            loop();
            RunPauseToggle.setCaptionLabel("Running");
        } else {
            noLoop();
            RunPauseToggle.setCaptionLabel("Paused");
        }
    }
    

    Hope this helps someone else...

  • Spoke too soon. Sketch appears to run fine with loop/noLoop controlling draw() action. But console outputs severe error and "check your code at runPause". Argh.

  • edited July 2017

    Can you post your whole code to reproduce your problem? One thing that comes to mind is calling noLoop(). I believe CP5 needs draw() to run to do its magic aka. to have the ability to interact with the user and to update variables and controller's member variables. I working example will help a lot here.

    Kf

  • kfrajer: here's the code. Thanks for taking a look. It runs fine with toggling to pause and run draw().

    /**
     * Simple heightfield 3D animation inside 2D window. 
     * <p>
     * Gaussian disturbance is exponential "pulse" generating 
     * point source for wave propagation.
     * <p>
     * Animations driven by differential operator on heightfield to produce 
     * vertical velocity increment which is used to make new heightfield.
     *
     */
    
    import controlP5.*;
    ControlP5 cp5;
    Toggle RunPauseToggle;
    
    // Parent 2D window contains 3D area and controlP5 controls
    int w2D = 1200;
    int h2D =  900;
    PFont font;
    
    // Inner 3D window for animated surface. Centered in Y, near left edge.
    PGraphics pg;
    int w3D = 800;
    int h3D = 800;
    float xOffset3D = (w2D - w3D) / 8;
    float yOffset3D = (h2D - h3D) / 2;
    
    // Locate family of controls relative to 3D, etc.
    int ctrlOffsetX = (int) xOffset3D+w3D+50;
    int ctrlOffsetY = (int) yOffset3D;
    int ctrlStepY   = 100;
    int ctrlSizeY   = 40;
    
    void settings() {
        size(w2D, h2D, P2D);
    }
    
    void setup() {
        frameRate(24);
        cp5 = new ControlP5(this);
        font = createFont("arial", 20);
        textFont(font);
    
        cp5.addTextlabel("fNumLabel")
           .setText("Frame number ")
           .setPosition(xOffset3D, yOffset3D / 4)
           .setSize(100, ctrlSizeY)
           .setFont(font)
           .setColorValue(0x00000000)
           ;
        RunPauseToggle = cp5.addToggle("runPause")
           .setPosition(ctrlOffsetX, ctrlOffsetY)
           .setSize(100, ctrlSizeY)
           .setFont(font)
           .setCaptionLabel("Running")
           .setColorCaptionLabel(0)
           .setValue(true)
           .setMode(ControlP5.SWITCH)
           ;
    
        // Create the dynamic 3D area and initialize it
        pg = createGraphics(w3D, h3D, P3D);
        init3dBase(pg);
        //noLoop();
    }
    
    void draw() {
        background(240);
        fill(100);
        text(frameCount, xOffset3D + 150, (yOffset3D / 4) + 20);
        make3dScene(pg);
        image(pg, xOffset3D, yOffset3D);
    
        // Evolve surface after initial frame
        convolve2D_4Pt(hf.z, hfLap.z, hf.nX, hf.nY, reflectBC);    // result in zdel2
        scaleArray(hfLap.z, hf.nX, hf.nY, 0.99);                  // dampen output
        addArrays(hf.z, hfLap.z, hf.nX, hf.nY);                    // merge back into z
    }
    
    public void runPause(boolean theFlag) {
        if (theFlag == true) {
            loop();
            RunPauseToggle.setCaptionLabel("Running");
        } else {
            noLoop();
            RunPauseToggle.setCaptionLabel("Paused");
        }
    }
    

    Thanks again.

  • In my haste I forgot to deactivate code that relies on files not present above.

    Please comment out the following lines: 64, and 71 through 77. The effect will still be demonstrated by the paused or running frame count. The console output - at least initial lines -- looks like this:

    ControlP5 2.2.6 infos, comments, questions at http://www.sojamo.de/libraries/controlP5
    Jul 04, 2017 1:03:16 AM controlP5.ControlBroadcaster printMethodError
    SEVERE: An error occured while forwarding a Controller event, please check your code at runPause
    java.lang.reflect.InvocationTargetException
        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)
    
  • http://www.sojamo.de/libraries/controlP5/examples/controllers/ControlP5toggle/ControlP5toggle.pde

    Try:

    boolean runPause=false; //GLOBAL scope

    and

    void draw() {
    
        if(runPause==true){
           return;
        }
    
        background(240);
        fill(100);
        text(frameCount, xOffset3D + 150, (yOffset3D / 4) + 20);
        make3dScene(pg);
        image(pg, xOffset3D, yOffset3D);
    
        // Evolve surface after initial frame
        convolve2D_4Pt(hf.z, hfLap.z, hf.nX, hf.nY, reflectBC);    // result in zdel2
        scaleArray(hfLap.z, hf.nX, hf.nY, 0.99);                  // dampen output
        addArrays(hf.z, hfLap.z, hf.nX, hf.nY);                    // merge back into z
    }
    

    Kf

  • I added your suggested code changes and got the same error with the opening lines of the console error message shown above. After many lines of traceback, the console message ends with this:

    Caused by: java.lang.NullPointerException
        at Heightfield_stripped.runPause(Heightfield_stripped.java:105)
        ... 25 more
    

    "Heightfield_stripped" is the name of the edited sketch I sent above. This ending message suggests the code is responding to the toggle event, runPause(boolean theFlag), but sees a null pointer. Yet, except for the console error dump, the sketch runs as expected.

  • Furthermore, if I comment out the runPause(boolean theFlag) toggle event response, then the startup error does not occur. Great. However, the RunPauseToggle.setCaptionLabel() command does not get executed so "RUNNING" persists. Also, frameCount is continuously incremented in the background so when the toggle to resume occurs, the displayed frameCount value jumps to the current value.

    We could just quit now on this problem. I didn't intend run/pause to be an important part of the user interface, I just started with it.

    Thanks for your continued thoughts on this.

  • Answer ✓

    I get the same error if I keep your lines 80 to 87. The reason is that you have two functions that the controller can address. This is my code:

    import controlP5.*;
    ControlP5 cp5;
    Toggle RunPauseToggle;
    
    // Parent 2D window contains 3D area and controlP5 controls
    int w2D = 1200;
    int h2D =  900;
    PFont font;
    
    // Inner 3D window for animated surface. Centered in Y, near left edge.
    PGraphics pg;
    int w3D = 800;
    int h3D = 800;
    float xOffset3D = (w2D - w3D) / 8;
    float yOffset3D = (h2D - h3D) / 2;
    
    // Locate family of controls relative to 3D, etc.
    int ctrlOffsetX = (int) xOffset3D+w3D+50;
    int ctrlOffsetY = (int) yOffset3D;
    int ctrlStepY   = 100;
    int ctrlSizeY   = 40;
    
    
    boolean runPause=false;  //GLOBAL scop
    
    void settings() {
      size(w2D, h2D, P2D);
    }
    
    void setup() {
      frameRate(24);
      cp5 = new ControlP5(this);
      font = createFont("arial", 20);
      textFont(font);
    
      cp5.addTextlabel("fNumLabel")
        .setText("Frame number ")
        .setPosition(xOffset3D, yOffset3D / 4)
        .setSize(100, ctrlSizeY)
        .setFont(font)
        .setColorValue(0x00000000)
        ;
      RunPauseToggle = cp5.addToggle("runPause")
        .setPosition(ctrlOffsetX, ctrlOffsetY)
        .setSize(100, ctrlSizeY)
        .setFont(font)
        .setCaptionLabel("Running")
        .setColorCaptionLabel(0)
        .setValue(true)
        .setMode(ControlP5.SWITCH)
        ;
    
      // Create the dynamic 3D area and initialize it
      pg = createGraphics(w3D, h3D, P3D);
      //init3dBase(pg);
      //noLoop();
    }
    
    void draw() {
    
        if(runPause==true){
           return;
        }
    
        background(240);
        fill(100);
        text(frameCount, xOffset3D + 150, (yOffset3D / 4) + 20);
        //make3dScene(pg);
        //image(pg, xOffset3D, yOffset3D);
    
        //// Evolve surface after initial frame
        //convolve2D_4Pt(hf.z, hfLap.z, hf.nX, hf.nY, reflectBC);    // result in zdel2
        //scaleArray(hfLap.z, hf.nX, hf.nY, 0.99);                  // dampen output
        //addArrays(hf.z, hfLap.z, hf.nX, hf.nY);                    // merge back into z
    }
    
    
    //public void runPause(boolean theFlag) {
    //    if (theFlag == true) {
    //        loop();
    //        RunPauseToggle.setCaptionLabel("Running");
    //    } else {
    //        noLoop();
    //        RunPauseToggle.setCaptionLabel("Paused");
    //    }
    //}
    

    Regarding the counter jumping after it resumes, it is the way it suppose to work. The variable frameCount is an internal counter. If you want to have your own controlled counter, you can create one easily.

    Kf

  • OK, I understand. I can live with a small side effect and will continue development. Thanks again.

Sign In or Register to comment.