2

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);}
  • Thank you. As I can see from your examples. I need to connect the first example with the last one. The task was to transfer data from the button (off, 10-60) to the controller, the button itself changes the text after pressing the required minutes. I wanted to do the same with the picture by drawing them in order. Of course, I don't need the picture to change from mouse hover, but only a click. – Вадим Кузьмин Aug 28 '20 at 11:28
  • It depends on your level of comfort with OOP/Java. If you're comfortable enough you could extend ControlP5's Button class, override `setImages(...)` to handle the custom images and use that. Otherwise, the custom behaviour with a picture changing only on click feels different enough from controlP5 that you will need a custom implementation (separate from controlP5): in this case my last answer is the closest. Be sure to replace the `getImage()` calls with `loadImage("0.png")`... after you add the images to the sketch. Good luck! – George Profenza Aug 28 '20 at 12:19

1 Answers1

1

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);
  }
  
}
George Profenza
  • 50,687
  • 19
  • 144
  • 218
  • Try them all, use the one that works best for your problem. I'm not sure I understood the problem 100% (hence multiple solutions). Hopefully that's close enough so you can tweak as needed to get to 100%. If the answer was helpful remember to vote up and mark it with the green check box if it solves the problem. – George Profenza Aug 28 '20 at 12:15
  • @ВадимКузьмин Saw you commend underneath your question a bit late. The last code snippet would be simplest. To test it out: 1. paste the code into a new sketch, 2. save the sketch, 3. drag the 0-6.png files on top of the sketch, 3. comment the `getImage` test version and commend back in the version bellow that uses `loadImage`. – George Profenza Aug 28 '20 at 13:48
  • Thank you, I'm close. There is one more thing, in the third example, the state of the button is read from the controller, which should reflect its setting. Whether the ControlP5plugTo method is applicable here. – Вадим Кузьмин Aug 29 '20 at 09:08
  • 1
    In the third example there is no controlp5 and therefore no controller/plugto() in that sense. The data (`min`) is stored within the button itself. Notice the `println` statement in the same sketch: that's an example of your access the data from outside the button class. This should work well as it is. Bare in mind adding two buttons means each will have its independent `min` variable. If you want two or more buttons accessing the same `min` piece of data you'll need to change the button logic a bit, but that's another separate question. – George Profenza Aug 29 '20 at 09:37
  • I checked the example, but I do not need to show the text of the button, its state, as I understand it, you need to hide the label? – Вадим Кузьмин Aug 29 '20 at 18:13
  • The picture changes because from the state showing the minutes. – Вадим Кузьмин Aug 29 '20 at 18:29
  • 1
    I'm sure you're more than capable of doing that buddy: just take our the `text()` call from the button class' `draw()` method. While you're at it you can probably get read of all the uses of the `label` string: probably don't need it anymore if you're not rendering text. Have fun ! – George Profenza Aug 29 '20 at 19:51
  • Got it, thank you as an intelligent person with an individual approach to everyone. – Вадим Кузьмин Aug 30 '20 at 08:17