Search code examples
user-interfacearduinoprocessingarduino-ideprocessing-ide

How to make button from an Image in Processing


The code I wrote is below. I want to make the REGION_1 and REGION_2 buttons from images(or shapes). I have 2 questions:

  1. I couldn't see a function for addButton that has the image feature. Is there a way to use an image directly as the button itself?

  2. Is there a way to make the buttons in the shape of rings? (No filled circles)

Here is the piece of my code and the screenshot from the UI:

  Group RegionGroup = cp5.addGroup("REGIONS")
    .setPosition(30,200)
    .setWidth(150)
    .setHeight(30)
    .setFont(font2)
    .moveTo(SetupGroup);
    background(0);
    noStroke();
    ;
        
    cp5.addButton("REGION_1")  // The button
    .setPosition(40,10)     // x and y relative to the group
    .setSize(90, 50)       // (width, height)
    .setFont(font)
    .moveTo(RegionGroup);   // add it to the group
    
    loadImage("button1.png"); //????
  ;     
  
  
    cp5.addButton("REGION_2")  // The button
    .setPosition(40,70)    // x and y relative to the group
    .setSize(90, 50)       // (width, height)
    .setFont(font) 
    .moveTo(RegionGroup);   // add it to the group
    
    loadImage("button2.png"); //?????
  ; 

enter image description here

enter image description here


Solution

  • You should be able to call setImage() on the button instance, for example:

    cp5.addButton("REGION_1")  // The button
        .setPosition(40,10)     // x and y relative to the group
        .setSize(90, 50)       // (width, height)
        .setFont(font)
        .moveTo(RegionGroup)
        .setImage(loadImage("button1.png"));   // add it to the group
        
    
    cp5.addButton("REGION_2")  // The button
    .setPosition(40,70)    // x and y relative to the group
    .setSize(90, 50)       // (width, height)
    .setFont(font) 
    .moveTo(RegionGroup)
    .setImage(loadImage("button2.png"));   // add it to the group
    

    If you have four images representing the four button states you could also do something like .setImages(yourPImageArrayHere);

    Regarding making the buttons in the shape of a circle, that would be possible via custom views, though the code would slightly more complex. You can use the ControlP5customView example as a starting point. Here's a modified version that displays the rings with no fills:

    /**
    * ControlP5 Custom View
    *
    *
    * find a list of public methods available for the ControllerDisplay Controller
    * at the bottom of this sketch.
    *
    * by Andreas Schlegel, 2012
    * www.sojamo.de/libraries/controlp5
    *
    */
    
    
    import controlP5.*;
    
    
    ControlP5 cp5;
    
    
    void setup() {
      size(400, 400);
      smooth();
      cp5 = new ControlP5(this);
      cp5.addButton("hello")
         .setPosition(50, 100)
         .setSize(150,150)
         .setView(new CircularButton())
         ;
         
      cp5.addButton("world")
         .setPosition(250, 100)
         .setSize(50,50)
         .setView(new CircularButton())
         ;
    }
    
    
    void draw() {
      background(ControlP5.BLACK);
    }
    
    public void hello(int theValue) {
      println("Hello pressed");
    }
    
    public void world(int theValue) {
      println("World pressed");
    }
    
    /**
     * to define a custom View for a controller use the ContollerView<T> interface
     * T here must be replace by the name of the Controller class your custom View will be 
     * applied to. In our example T is replace by Button since we are aplpying the View 
     * to the Button instance create in setup. The ControllerView interface requires
     * you to implement the display(PApplet, T) method. Same here, T must be replaced by
     * the Controller class you are designing the custom view for, for us this is the 
     * Button class. 
     */
     
    class CircularButton implements ControllerView<Button> {
    
      public void display(PGraphics theApplet, Button theButton) {
        theApplet.pushMatrix();
        theApplet.noFill();
        theApplet.strokeWeight(9);
        if (theButton.isInside()) {
          if (theButton.isPressed()) { // button is pressed
            theApplet.stroke(ControlP5.LIME);
          }  else { // mouse hovers the button
            theApplet.stroke(ControlP5.YELLOW);
          }
        } else { // the mouse is located outside the button area
          theApplet.stroke(ControlP5.GREEN);
        }
        
        theApplet.ellipse(0, 0, theButton.getWidth(), theButton.getHeight());
        
        // center the caption label 
        int x = theButton.getWidth()/2 - theButton.getCaptionLabel().getWidth()/2;
        int y = theButton.getHeight()/2 - theButton.getCaptionLabel().getHeight()/2;
        
        translate(x, y);
        theButton.getCaptionLabel().draw(theApplet);
        
        theApplet.popMatrix();
      }
    }
    
    
    /*
    a list of all methods available for the ControllerView Controller
    use ControlP5.printPublicMethodsFor(ControllerView.class);
    to print the following list into the console.
    
    You can find further details about class ControllerView in the javadoc.
    
    Format:
    ClassName : returnType methodName(parameter type)
    
    controlP5.ControllerView : void display(PApplet, T)
    
    */
    

    This is more complex but also flexible. If this is not something worthwhile you could probably get away with making rings with no fills as transparent png skins for the button (using setImage() / setImages())