javaprocessingcontrol-p5

Change the picture when pressing the button


Tell me how to make it change to the next one when you click on a picture. I use a library "ControlP5, cp5.addbutton" with a regular button in which I could do without a picture. I have two examples, with a regular button and a picture, where I use a different way to change the picture by hovering the mouse and clicking in order to show you clearly. enter image description here

enter image description here

"minutesss1" - a regular button with public void minutesss1() which uses .setCaptionLabel("ВЫКЛ"). "minutesss2" - How I think to use for the picture .setCaptionLabel("ВЫКЛ") / Not required ?????

Complete example code:

import controlP5.*;
ControlP5 cp5;
int min=0;
Button minutess1;
Button minutess2;

void setup() {
  size(700,400);
  
  PFont fontn = createFont("Times New Roman",18);
  cp5 = new ControlP5(this);
  PFont p = createFont("Times New Roman",18);
  ControlFont font=new
  ControlFont(p);
  cp5.setFont(font);
  
    minutess1 = cp5.addButton("minutesss1")
    .setCaptionLabel("ВЫКЛ")
    .setPosition(200,200)
    .setSize(99,25);
    
    PImage[] imgs1 = {loadImage("0.png"),loadImage("1.png"),loadImage("2.png")}; // ,loadImage("3.png"),loadImage("4.png"),loadImage("5.png"),loadImage("6.png")
    minutess2 = cp5.addButton("minutesss2")
    //.setCaptionLabel("ВЫКЛ")
    .setPosition(400,200)
    .setImages(imgs1);
    minutess2.setSize(99,25);
  
textFont(fontn);}
  public void minutesss1() {
  min+=10;
 if (min>60) {min=0; minutess1.setCaptionLabel("ВЫКЛ"); }
  else  minutess1.setCaptionLabel(str(min)+" Мин");}
void draw(){
  background(0);
  fill(255);}

Solution

  • It's great that you've posted the code formatted like that. It would be even better if you format it in Processing (Ctrl + T) before to make it easier to read.

    It is difficult to fully understand what your asking. If you're using a translation tool you can try breaking long phrases into smaller, simpler sentences. Hopefully the translation tool will do a better job.

    From what I can understand there are two questions here:

    1. How can you call the same minutes updating function that works for the first button from the second button ?
    2. How can you use custom images to skin the second button ?

    The first question can be tackled multiple ways. Here are a couple of options:

    Option 1: Use controlEvent which gets called automatically when updating any controlP5 component. You can check which button was pressed and call a function accordingly:

    import controlP5.*;
    ControlP5 cp5;
    int min=0;
    Button minutess1;
    Button minutess2;
    
    void setup() {
      size(700, 400);
    
      PFont fontn = createFont("Times New Roman", 18);
      cp5 = new ControlP5(this);
      PFont p = createFont("Times New Roman", 18);
      ControlFont font=new
        ControlFont(p);
      cp5.setFont(font);
    
      minutess1 = cp5.addButton("minutesss1")
        .setCaptionLabel("ВЫКЛ")
        .setPosition(200, 200)
        .setSize(99, 25);
    
      //PImage[] imgs1 = {loadImage("0.png"), loadImage("1.png"), loadImage("2.png")}; // ,loadImage("3.png"),loadImage("4.png"),loadImage("5.png"),loadImage("6.png")
      PImage[] imgs1 = {getImage(99,25,color(0,0,192)),
                        getImage(99,25,color(0,0,240)),
                        getImage(99,25,color(0,0,120))};
      minutess2 = cp5.addButton("minutesss2")
        //.setCaptionLabel("ВЫКЛ")
        .setPosition(400, 200)
        .setImages(imgs1);
      minutess2.setSize(99, 25);
    
      textFont(fontn);
    }
    
    PImage getImage(int w, int h, int c){
      PImage img = createImage(w, h, RGB);
      java.util.Arrays.fill(img.pixels, c);
      img.updatePixels();
      return img;
    }
    
    public void minutesss1() {
      min+=10;
      if (min>60) {
        min=0; 
        minutess1.setCaptionLabel("ВЫКЛ");
      } else  minutess1.setCaptionLabel(str(min)+" Мин");
      println(min,minutess1.getCaptionLabel().getText());
    }
    
    void draw() {
      background(0);
      fill(255);
    }
    
    public void controlEvent(ControlEvent event) {
      if(event.controller() == minutess2){
        minutesss1();
      }
    }
    

    Option 2: Extract the instructions of the first button press function into a separate function that can be called by both. This is probably simpler and more intuitive to read:

    import controlP5.*;
    ControlP5 cp5;
    int min=0;
    Button minutess1;
    Button minutess2;
    
    void setup() {
      size(700, 400);
    
      PFont fontn = createFont("Times New Roman", 18);
      cp5 = new ControlP5(this);
      PFont p = createFont("Times New Roman", 18);
      ControlFont font=new
        ControlFont(p);
      cp5.setFont(font);
    
      minutess1 = cp5.addButton("minutesss1")
        .setCaptionLabel("ВЫКЛ")
        .setPosition(200, 200)
        .setSize(99, 25);
    
      //PImage[] imgs1 = {loadImage("0.png"), loadImage("1.png"), loadImage("2.png")}; // ,loadImage("3.png"),loadImage("4.png"),loadImage("5.png"),loadImage("6.png")
      // don't have images to reproduce: making new ones
      PImage[] imgs1 = {getImage(99,25,color(0,0,192)),
                        getImage(99,25,color(0,0,240)),
                        getImage(99,25,color(0,0,120))};
      minutess2 = cp5.addButton("minutesss2")
        //.setCaptionLabel("ВЫКЛ")
        .setPosition(400, 200)
        .setImages(imgs1);
      minutess2.setSize(99, 25);
    
      textFont(fontn);
    }
    
    PImage getImage(int w, int h, int c){
      PImage img = createImage(w, h, RGB);
      java.util.Arrays.fill(img.pixels, c);
      img.updatePixels();
      return img;
    }
    
    void updateMinutes(){
      min+=10;
      if (min>60) {
        min=0; 
        minutess1.setCaptionLabel("ВЫКЛ");
      } else  minutess1.setCaptionLabel(str(min)+" Мин");
      println(min,minutess1.getCaptionLabel().getText());
    }
    
    public void minutesss1() {
      updateMinutes();  
    }
    
    public void minutesss2() {
      updateMinutes();  
    }
    
    void draw() {
      background(0);
      fill(255);
    }
    

    Regarding the second part of your question it's unclear if you want to have images just for the default controlP5 states(default, over, active, highlight) using setImages() or not. If you pass more than 4 or less than 3 images they will be ignored as you can see in the source code

    If you want to display a different image for each minutes update (e.g. off, 10 , 20, 30, 40, 50, 60) then you will need to make your own custom button. The logic isn't that complicated and you can use the Button Example as a simpler starting point.

    It would be great to encapsulate that more complex custom functionality and you'd need a few Object Oriented Programming (OOP) basics for that. You can check out the Objects tutorial and example

    For illustration purposes here's a separate sketch that would display a different image for each of the button press states (ignoring the over/highlight states):

    ImageButton button;
    
    void setup(){
      size(300, 300);
      // button dimensions
      int w = 75;
      int h = 25;
      // test with generated images
      button = new ImageButton(112, 137, w, h, 
                   new PImage[]{
                     // use loadImage with your own images instead of getImage :)
                     getImage(w, h, color(192, 0, 32 * 2)), // off
                     getImage(w, h, color(0, 0, 32 * 3)), // 10
                     getImage(w, h, color(0, 0, 32 * 4)), // 20
                     getImage(w, h, color(0, 0, 32 * 5)), // 30
                     getImage(w, h, color(0, 0, 32 * 6)), // 40
                     getImage(w, h, color(0, 0, 32 * 7)), // 50
                     getImage(w, h, color(0, 0, 32 * 8)), // 60
                   });
                   
      // loading images will be something similar to:
      //button = new ImageButton(112, 137, w, h, 
      //             new PImage[]{
      //               loadImage("0.png"), // off
      //               loadImage("1.png"), // 10
      //               loadImage("2.png"), // 20
      //               loadImage("3.png"), // 30
      //               loadImage("4.png"), // 40
      //               loadImage("5.png"), // 50
      //               loadImage("6.png"), // 60
      //             });
    }
    
    void draw(){
      background(0);
      button.draw();
    }
    
    void mousePressed(){
      button.mousePressed(mouseX,mouseY);
      println(button.min);
    }
    
    // test images to represent loaded state images
    PImage getImage(int w, int h, int c){
      PImage img = createImage(w, h, RGB);
      java.util.Arrays.fill(img.pixels, c);
      img.updatePixels();
      return img;
    }
    
    // make a custom image button class
    class ImageButton{
      // minutes is the data it stores
      int min = 0;
      // images for each state
      PImage[] stateImages;
      // which image to display
      int stateIndex;
      // position
      int x, y;
      // dimensions: width , height
      int w, h;
      // text to display
      String label = "ВЫКЛ";
      
      ImageButton(int x, int y, int w, int h, PImage[] stateImages){
        this.x = x;
        this.y = y;
        this.w = w;
        this.h = h;
        this.stateImages = stateImages;
      }
      
      void mousePressed(int mx, int my){
        // check the cursor is within the button bounds
        boolean isOver = ((mx >= x && mx <= x + w) &&  // check horizontal
                          (my >= y && my <= y + h) );  // check vertical
                  
        if(isOver){
          
          min += 10;
          stateIndex++;
          
          if (min>60) {
            min = 0; 
            stateIndex = 0;
            label = "ВЫКЛ";
          } else  {
            label = min + " Мин";
          }
          
        }
      }
      
      void draw(){
        // if the images and index are valid
        if(stateImages != null && stateIndex < stateImages.length){
          image(stateImages[stateIndex], x, y, w, h);
        }else{
          println("error displaying button state image");
          println("stateImages: ");
          printArray(stateImages);
          println("stateIndex: " + stateIndex);
        }
        // display text
        text(label, x + 5, y + h - 8);
      }
      
    }