Passing ControlP5 checkBox values from ControlFrame window to main sketch

edited December 2013 in Library Questions

I have a ControlFrame that allows the user to adjust application parameters in the main sketch. The sliders work fine (lifted right out of the example). Textboxes also work for me (though only in P2.0.3, not 2.1). However, I want the user to set values that can be toggled on/off and I'm using the CP5 checkBox for that. However, I can't get it to pass the true/false value back to the main sketch. It doesn't seem to use the toParent method like the others. I've been through the forum and the ControlP5 docs but can't track this one down. Any suggestions? Thanks in advance for the help.

I've extracted the salient code from my application. All works except for the CheckBox.

    import java.awt.Frame;          //  2nd Window add
    import java.awt.BorderLayout;   //  2nd Window add

    String tableWidth = "7";
    String tableLength = "13";
    int def = 140; //background color
    int tableAlpha = 20; // table transparency
    Boolean modelRenderOn = true;  //Toggle on-screen rendering

    private ControlP5 cp5;  
    ControlFrame cf;        // ControlP5 control frame (2nd window)

    cf = addControlFrame("Config", 200,400);   //  <===============  Control Window Size, Name

// The usual SetUp, Draw Loop and otehr application functions in here

    //==================================================================== CODE FOR CONTROL WINDOW

    ControlFrame addControlFrame(String theName, int theWidth, int theHeight) {
      Frame f = new Frame(theName);
      ControlFrame p = new ControlFrame(this, theWidth, theHeight);
      f.add(p);
      p.init();
      f.setTitle(theName);
      f.setSize(p.w, p.h);
      f.setLocation(100, 100);
      f.setResizable(true);
      f.setVisible(true);
      return p;
    }

    public class ControlFrame extends PApplet {

      int w, h;

      int abc = 100;

      public void setup() {
        size(w, h);
        frameRate(25);
        def = 140;
        cp5 = new ControlP5(this);
        cp5.addSlider("abc").setRange(0, 255).setPosition(10,10);
        cp5.addSlider("def").plugTo(parent,"def").setRange(0, 255).setPosition(10,30).setValue(140);
        cp5.addTextfield("tableWidth").plugTo(parent,"tableWidth").setPosition (10,50).setSize(20,15).setAutoClear(false);
        cp5.addTextfield("tableLength").plugTo(parent,"tableLength").setPosition (10,85).setSize(20,15).setAutoClear(false);
        cp5.addSlider("Table Alpha").plugTo(parent,"tableAlpha").setRange(0, 255).setPosition(10,120).setValue(60);  
        cp5.addCheckBox("Model Display").setPosition(10,140).setColorForeground(color(120)).setColorActive(color(0,255,0)).setColorLabel(color(255)).setSize(20,20).addItem("Render_Model",0).plugTo(parent,"modelRenderOn"); // THIS DOESN'T WORK
    }

      public void draw() {
          background(abc);
      }

//      public void Render_Model(){  // This is another attempt to pass boolean parameter back to main sketch window. However main sketch global vars from main sketch don't carry through separate frame/window
//        if (modelRenderOn){
//         modelRenderOn = false;
//        }else{
//         modelRenderOn = true;
//        }
//      }

      private ControlFrame() {
      }

      public ControlFrame(Object theParent, int theWidth, int theHeight) {
        parent = theParent;
        w = theWidth;
        h = theHeight;
      }


      public ControlP5 control() {
        return cp5;
      }


      ControlP5 cp5;

      Object parent;


    }

Answers

  • Hi, plugTo will not work for groups (like a checkbox) therefore there are 2 alternatives. 1) use toggles 2) use controlEvent inside the ControlFrame class, see below:

    public void controlEvent(ControlEvent theEvent) {
        if(theEvent.isFrom("Model Display")) {
          print("Event from Model Display ");
          println(theEvent.getArrayValue());
          // pass state to parent class
          modelRenderOn = (theEvent.getArrayValue()[0]==0) ? false:true;
        }
      }
    
  • Thank you. My preference is to use toggles (since that's the behavior I was using checkboxes for). However, I had expected the following code to work:

    cp5.addToggle("ModelDisplay")
         .setPosition(10,140)
         .setSize(50,20)
         .plugTo(parent,"modelRenderOn")
         ;
    

    but it has no effect. Since the toggle has a set instance value, and no array, shouldn't the .plugTo method work to apss the 1/0 to the boolean variable in the main app?

    Also, any idea how to make the secondary frame/window persistent on top?

    Thanks

  • edited December 2013

    Adding your toggle to the controlP5frame example works for me. use f.setAlwaysOnTop( true ); to keep a frame always on top - in the example below, put it after f.setVisible(true);

    import java.awt.Frame;
    import controlP5.*;
    // using processing 2.1 and controlP5 2.0.4
    ControlP5 cp5;
    ControlFrame cf;
    
    int def;
    boolean modelRenderOn = false;
    
    void setup() {
      size(400, 400);
      cp5 = new ControlP5(this);
      cf = addControlFrame("extra", 200,200);
    }
    
    void draw() {
      background(def);
      println(modelRenderOn);
    }
    
    ControlFrame addControlFrame(String theName, int theWidth, int theHeight) {
      Frame f = new Frame(theName);
      ControlFrame p = new ControlFrame(this, theWidth, theHeight);
      f.add(p);
      p.init();
      f.setTitle(theName);
      f.setSize(p.w, p.h);
      f.setLocation(100, 100);
      f.setResizable(false);
      f.setVisible(true);
      return p;
    }
    
    public class ControlFrame extends PApplet {
      int w, h;
      int abc = 100;
      public void setup() {
        size(w, h);
        frameRate(25);
        cp5 = new ControlP5(this);
        cp5.addSlider("abc").setRange(0, 255).setPosition(10,10);
        cp5.addSlider("def").plugTo(parent,"def").setRange(0, 255).setPosition(10,30);
        cp5.addToggle("ModelDisplay")
         .setPosition(10,140)
         .setSize(50,20)
         .plugTo(parent,"modelRenderOn")
         ;
      }
    
      public void draw() {
          background(abc);
      }
    
      private ControlFrame() {
      }
    
      public ControlFrame(Object theParent, int theWidth, int theHeight) {
        parent = theParent;
        w = theWidth;
        h = theHeight;
      }
    
      public ControlP5 control() {
        return cp5;
      }
    
      ControlP5 cp5;
      Object parent;
    
    }
    
  • Thank you so much for your help with this. Gosh, I'm stumped :(

    My code looks identical to your example. However, I can run the snippet above on its own and it works. I have the identical code in my primary application but something seems to be clashing or blocking the toggle messaging between the frame and the main app as the modelRenderOn variable never changes in the main app. My other controls in the frame work, just not this one. This is feeling like some silly little obvious thing is wrong and I just can't see it at the moment. I checked to make sure I didn't have any other controls or code overwriting that variable and that's not the issue.

    Here's the salient code that doesn't work copied straight from my application:

    import processing.opengl.*;
    import controlP5.*;
    import peasy.*;
    import processing.serial.*; //Serial Drivers
    import sojamo.drop.*;
    import java.util.Locale;        //  P2 change
    import java.awt.event.KeyEvent; //  P2 change
    import java.awt.Frame;          //  2nd Window add
    import java.awt.BorderLayout;   //  2nd Window add
    
    Boolean modelRenderOn = true;  //Toggle on-screen rendering
    
    void draw() {
    
      println(modelRenderOn);
    
       if (modelRenderOn){     // this enables the rendering toggle
       processModel();
       }else{
         fill(255,0,0);
         text("RENDERING TURNED OFF",scaleFactor*.5,-scaleFactor*.5);
       }
    }
    
    //==================================================================== CODE FOR CONTROL WINDOW
    
    ControlFrame addControlFrame(String theName, int theWidth, int theHeight) {
      Frame f = new Frame(theName);
      ControlFrame p = new ControlFrame(this, theWidth, theHeight);
      f.add(p);
      p.init();
      f.setTitle(theName);
      f.setSize(p.w, p.h);
      f.setLocation(100, 100);
      f.setResizable(true);
      f.setVisible(true);
      return p;
    }
    
    
    public class ControlFrame extends PApplet {
    
      int w, h;
      int abc = 100;
    
      public void setup() {
        size(w, h);
        frameRate(25);
        def = 140;
        cp5 = new ControlP5(this);
        cp5.addSlider("abc").setRange(0, 255).setPosition(10,10);
        cp5.addSlider("def").plugTo(parent,"def").setRange(0, 255).setPosition(10,30).setValue(140);
        cp5.addTextfield("tableWidth").plugTo(parent,"tableWidth").setPosition (10,50).setSize(20,15).setAutoClear(false);
        cp5.addTextfield("tableLength").plugTo(parent,"tableLength").setPosition (10,85).setSize(20,15).setAutoClear(false);
        cp5.addSlider("Table Alpha").plugTo(parent,"tableAlpha").setRange(0, 255).setPosition(10,120).setValue(60);
      cp5.addToggle("ModelDisplay")
         .setPosition(10,140)
         .setSize(50,20)
         .plugTo(parent,"modelRenderOn")
         ;  
        }
    
      public void draw() {
          background(abc);
      }
    
    
    
      private ControlFrame() {
      }
    
      public ControlFrame(Object theParent, int theWidth, int theHeight) {
        parent = theParent;
        w = theWidth;
        h = theHeight;
      }
    
    
      public ControlP5 control() {
        return cp5;
      }
    
    
      ControlP5 cp5;
      Object parent;
    
    
    }
    // =====================================================  END CONTROL WINDOW
    
  • Answer ✓

    Hi, the type of variable modelRenderOn in your case should be boolean (with a lowercase b) not Boolean (with a capital B).

  • Oh my Gosh! I hadn't even noticed that - it now works fine, mystery resolved.

    Many thanks!

  • edited January 2014

    I have my parameters and variable values passing back and forth between the main frame and the ControlFrame. However I've hit another mysterious snag using the ControlFrame with image buttons. I have an image button in my main window code and it works great. However the same code doesn't work in the ControlFrame. I suspect that the Controlframe has a different default path and the loadImage doesn't work? Any suggestions are very welcome.

    Here's my code inside the new ControlFrame (same as prior code):

      public void setup() {
        size(w, h);
        frameRate(25);
        int mainSh, configSh, tableA;
        mainSh = int(mainShade);
        configSh = int(configShade);
        tableA = int(tableAlpha);
    
        PImage save_norm = loadImage("save_norm.png"); // already tried loadImage in button definition
        PImage save_hover = loadImage("save_hover.png");
        PImage save_click = loadImage("save_click.png");
    
        cp5 = new ControlP5(this);
        cp5.addSlider("configShade")
        .setLabel("Config Window Shade")
        .plugTo(parent,"configShade")
        .setRange(0, 255)
        .setPosition(10,10)
        .setValue(configSh)
        ;
        cp5.addSlider("def")
        .setLabel("Render Window Shade")
        .plugTo(parent,"mainShade")
        .setRange(0, 255)
        .setPosition(10,30)
        .setValue(mainSh)
        ;
        cp5.addTextfield("tableWidth")
        .setLabel("Table Width")
        .plugTo(parent,"tableWidth")
        .setPosition (10,50)
        .setSize(20,15)
        .setAutoClear(false)
        .setValue(tableWidth);
        ;
        cp5.addTextfield("tableLength")
        .setLabel("Table Length")
        .plugTo(parent,"tableLength")
        .setPosition (90,50)
        .setSize(20,15)
        .setAutoClear(false)
        .setValue(tableLength);
        ;
        cp5.addSlider("Table Alpha")
        .setLabel("Table Transparency")
        .plugTo(parent,"tableAlpha")
        .setRange(0, 255)
        .setPosition(10,90)
        .setValue(tableA)
        ;
        cp5.addToggle("ModelDisplay")
         .setPosition(10,110)
         .setSize(20,20)
         .plugTo(parent,"modelRenderOn")
         .setLabel("Model Render on/off")
         .setValue(-1)
         ;  
        cp5.addButton("saveConfig")
         .setPosition(10, 180)
         //.setSize(60,60)
         .setImages(save_norm, save_hover, save_click)
         .setLabel("Save Config")
         .updateSize()
         ;
    
        }
    

    This throws the following errors:

    The file "save_norm.png" is missing or inaccessible, make sure the URL is valid or that the file has been added to your sketch and is readable.
    The file "save_hover.png" is missing or inaccessible, make sure the URL is valid or that the file has been added to your sketch and is readable.
    The file "save_click.png" is missing or inaccessible, make sure the URL is valid or that the file has been added to your sketch and is readable.
    
Sign In or Register to comment.