0

I have OKNO1 and OKNO2, I want to show a button with an image strictly in OKNO1.

At the moment, the button with the image is shown globally. I used to use cp5.addButton and there I did it with .moveTo("okno1");

Now the image button uses OOP/Java. How to solve a tricky problem? What ways can you do the task. I think to use again void draw().

enter image description hereenter image description here

Complete code example:

import controlP5.*;
ControlP5 cp5;
ImageButton button;
Textlabel I;
Textlabel tempIn;

void setup() {
  size(700, 420, P3D);
  surface.setResizable(false);
  smooth();
  frameRate(30);
  cp5 = new ControlP5(this);

  PFont p = createFont("Times New Roman", 18);
  ControlFont font=new
    ControlFont(p);
  cp5.setFont(font);

  cp5.addTab("okno2")
    .setColorBackground(color(0, 160, 100))
    .setColorLabel(color(255))
    .setColorActive(color(255, 128, 0));

  cp5.getTab("default")
    .activateEvent(true)
    .setLabel("okno1")
    .setId(1);

  cp5.getTab("okno2")
    .activateEvent(true)
    .setId(2);

  tempIn = cp5.addTextlabel("Sostoyanie")
    .setText("1")
    .setFont(createFont("Times New Roman", 20))
    .setColor(color(0xffffff00))
    .setPosition(155, 35);

  I = cp5.addTextlabel("Impuls")
    .setText("2")
    .setPosition(155, 35)
    .setFont(createFont("Times New Roman", 20))
    .setColor(color(0xffffff00))
    .moveTo("okno2");

  int w = 99;
  int h = 25;
  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);
}
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;
}
class ImageButton {
  int min = 0;
  PImage[] stateImages;
  int stateIndex;
  int x, y;
  int w, h;
  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) {
    boolean isOver = ((mx >= x && mx <= x + w) &&
      (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 (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);
    }
}
4

1 回答 1

2

Help others (including myself) help you:

  • keep the code tidy (remove anything that is unnecessary, like the getImage for example)
  • format the code so it's easy to read. I can't stress this enough.

To help yourself always make sure you understand all your code completely:

  • read it
  • imagine in your head how it would run
  • run it and observe the actual behaviour
  • understand what was different between your mental model and what the computer did.

This will help you debug code in general. Also checkout Kevin Workman's Debugging tutorial.

Regarding your issue: the button is rendered all the time in draw(). You want to only draw it when the first tab is active hence:

  • get the first tab
  • check if it's active
  • if so, render the button

e.g instead of button.draw() you'd use:

if(cp5.getTab("default").isActive()){
    button.draw();
  }

That will do the trick, but as you interface gets more complex, you may want group what's being drawn per tab. Here's an idea on how to organise for a UI with more controls per tab:

  • add a global variable (at the top of your code) to keep track of the current tab: int currentTab = 1;
  • call displayTabs(); in draw() instead of button.draw() to handle per tab drawing. (More about displayTabs() bellow)
  • controlEvent() to update the currentTab

Like so:

void controlEvent(ControlEvent event) {
  // update current tab only if the current event comes from a tab (and not other controllers) 
  if(event.isTab()){
    currentTab = event.getId();
  }
}

The idea is controlEvent will get triggered when any ControlP5 component (controller) is clicked/updated. If it's a tab you can update currentTab to know in draw() which content to draw() using displayTabs():

void displayTabs(){
  switch(currentTab){
    case 1:
      displayTab1();
      break;
    case 2:
      displayTab2();
      break;
  }
}

void displayTab1(){
  button.draw();
}

void displayTab2(){
  // render stuff for tab 2 only
}

So there's one switch with calls one function or another depending on the currentTab value. The advantage of doing things this was is that you can easily replicate another case for another tab in the future and each tab content is neatly compartmentalised.

于 2020-09-01T10:57:29.260 回答