Number box like Pure Data

Nailed it.

Made a number box like Pure Data but it still needs some work, any suggestions?

PFont f; // STEP 1 Declare PFont variable

int boton1X, boton1Y, boton1Size;  // Boton1
boolean boton1Over, boton1Presionado;

int contador, restador, velocidad, divisor;  // Contador
String contad = "0";

int contadorBoxX, contadorBoxY, contadorBoxSize;  // Recuadro para cambiar numero
boolean contadorBoxOver, contadorBoxPresionado;

int mX, mY, mouseXdelta, mouseYdelta; // Mouse drag

void setup() {
  velocidad = 30;
  size(640, 360);
  background(255);
  frameRate(velocidad);

  f = createFont("Arial", 30, true); // Create Font

  boton1Size = 40;  //Parametros del boton play
  boton1X = 10;
  boton1Y = 10;

  contadorBoxSize = 35;
  ;  //Parametros del recuadro para cambiar numero
  contadorBoxX = 10;
  contadorBoxY = 100;
}

void draw() {
  background(255);
  // TEXTO
  textFont(f);    // Specify font to be used
  textAlign(LEFT, CENTER);
  fill(0);    // Specify font color RGB 
  text("Ubicación " + contad, contadorBoxX+10, contadorBoxY+15);    // Display Text, debe ajustarse a la mitad del tamaño arriba y abajo
  // BOTON PLAY
  updateBotonPlay(boton1X, boton1Y, boton1Size, boton1Size); // Update para el boton de play
  if (boton1Over) {
    stroke(100, 255, 0);
  } else {
    stroke(255, 255, 255);
  };
  if (boton1Presionado) {
    fill(0, 255, 0);
  } else {
    fill(255, 0, 0);
  };
  strokeWeight(4);
  rect(boton1X, boton1Y, boton1Size, boton1Size, 6);
  // RECUADRO CAJA DE NUMERO
  updateRecuadroNumero(contadorBoxX, contadorBoxY, contadorBoxSize+300, contadorBoxSize); // Update para el recuadro de numero
  if (contadorBoxPresionado) {
    stroke(255, 255, 0);
    strokeWeight(4);
  } else if (contadorBoxOver) {
    stroke(255, 200, 0);
    strokeWeight(1);
  } else {
    stroke(255, 100, 0);
    strokeWeight(1);
  };
  noFill();
  rect(contadorBoxX, contadorBoxY, contadorBoxSize+300, contadorBoxSize, 6);
  // EMPEZAR A CONTAR
  if (boton1Presionado) {
    conta(); // Funcion contador
  }
}

void updateBotonPlay(int x, int y, int w, int h) { // Funcion Update para el boton play
  if (mouseX >= x && mouseX <= x+w && 
    mouseY >= y && mouseY <= y+h) {
    boton1Over = true;
  } else {
    boton1Over = false;
  }
}

void updateRecuadroNumero(int x2, int y2, int w2, int h2) { // Funcion Update para el boton play
  if (mouseX >= x2 && mouseX <= x2+w2 && 
    mouseY >= y2 && mouseY <= y2+h2) {
    contadorBoxOver = true;
    //println("aqui taaa");
  } else {
    contadorBoxOver = false;
  }
}
// ==================================FUNCIONES DEL MOUSE

void mousePressed() {
  // BOTON PRESIONADO
  if (boton1Over) {
    boton1Presionado = !boton1Presionado;  //cambia el estado del boton
  } // if
  if (contadorBoxOver) {
    mY = mouseY;
    contadorBoxPresionado = true;  //cambia el estado del boton
    //print(mY);
  } // if
  else{
    contadorBoxPresionado = false;
  }
} // CAJA DE NUMERO PRESIONADA

void mouseDragged() {
  if (contadorBoxPresionado) {
    contador = int(contad);
    mouseYdelta = mY - mouseY;
    contador = contador + floor ( mouseYdelta / 32 );
    contad = str(contador);
    println(contador);
  }
}

// ==================================FUNCIONES DEL TECLADO ALFANUMERICO
void keyTyped() {
}//func 

void keyPressed() {
  if (contadorBoxPresionado) { // Funciones de texto para el recuadro de número
    if (key==CODED) {
    } // if
    else {
      if (key==BACKSPACE) {
        if (contad.length()>0) {
          contad=contad.substring(0, contad.length()-1);
        } // if
      } // if
      else if (key=='\n') {
        contador = int(contad);
        contadorBoxPresionado = false;
      } // else if
      else {
        if (key == '1' || key == '2' || key == '3'|| key == '4'|| key == '5'|| key == '6'|| key == '7'|| key == '8'|| key == '9'|| key == '0') {
          contad+=key;
        } // if teclas numericas
        else {
          println("sólo teclas numéricas");
        }
      } // else
      // output
      //println (contad);
    } // else
  } // if contadorBoxPresionado
} //func

// ==================================FUNCIONES DEL CONTADOR
void conta() {
  restador = frameCount;
  divisor = 4;
  if ((frameCount % divisor) == 0) {
    contador = int(contad);
    contador++;
    contad = str(contador);
  }
}

1 Like

Can you please elaborate?

What is a number box?

This is a PD number box:

Yes, I think it is easy to convert. I’m using the frameCount to count. So if I do counter + 0.1, rather than counter++ I’ll get floating point.

I was asking for ideas to make it better, thank you anyway

Oh, you are commenting other comment, sorry

Congratulations – great work! Thanks for sharing this.

You might also be interested in the numberbox implementation in ControlP5.

import controlP5.*;
ControlP5 cp5;
float numberbox;  // updated by corresponding control name "numberbox"

void setup() {
  size(256, 256);
  cp5 = new ControlP5(this);
  cp5.addNumberbox("numberbox")
    .setPosition(width/2-50, height/2-10)
    .setSize(100, 20)
    .setRange(0, 256)
    .setDirection(Controller.VERTICAL)  // mouse input
    .setMultiplier(1.0)  // units changed per mouse pixel moved
    .setValue(128)
    ;
}

void draw() {
  background(numberbox);
}

For the full documentation, see the ControlP5numberbox example sketch and/or the reference page: Numberbox (Javadocs: controlP5)

That version does not accept text input. There is an example sketch which does:

experimental/ControlP5editableNumberbox.pde

It is a bit touchy, as it deactivates input mode any time the mouse leaves the box screen area, which to my mind is a bit counterintuitive. You could try to remove and replace the .onLeave callback, but I’m not sure if ControlP5 has an easy way to deactivate on click-outside; after looking around I suspect perhaps not.

If you are moving on with your own solution, I would suggest perhaps try a class-based approach next? That will make it easier to create many numboxes and interact with each one separately.

Here is a minimal example with two number boxes. It doesn’t have keyboard input support, although that could be added…

/**
 * PDnumboxExample
 * 2020-05-21 Jeremy Douglass - Processing 3.5.4
 * discourse.processing.org/t/number-box-like-pure-data/21064
 */

ArrayList<PDcontrol> controls;

void setup() {
  controls = new ArrayList<PDcontrol>();
  controls.add(new PDnumbox(width/2-25, height/2-20, 50, 20));
  controls.add(new PDnumbox(5, 5, 50, 20));
}

void draw() {
  background(192);
  for(PDcontrol c : controls) c.display();
}

void mousePressed() {
  for(PDcontrol c : controls) c.press(mouseX, mouseY);
}

void mouseReleased() {
  for(PDcontrol c : controls) c.release(mouseX, mouseY);
}

void mouseDragged() {
  for(PDcontrol c : controls) c.drag(0, pmouseY - mouseY);
}

class PDnumbox extends PDcontrol{
  float val;
  
  PDnumbox (float x, float y, float w, float h) {
    this.x = x;
    this.y = y;
    this.w = w; 
    this.h = h;
    this.val = 0;
  }
  
  void display() {
    pushStyle();
    textAlign(CENTER, CENTER);
    fill(255);
    rect(x, y, w, h);
    fill(0);
    text(str(val), x+w/2, y+h/2);
    popStyle();
  }
  
  boolean drag(float dx, float dy) {
    if(selected) { 
      val += dy;
      return true;
    }
    return false;
  }
}

abstract class PDcontrol{
  float x, y, w, h;
  boolean selected;

  void display() {
  }

  boolean drag(float dx, float dy) {
    return false;
  }

  boolean over(float px, float py) {
    return (px >= x && px <= x + w &&  py >= y && py <= y + h) ? true : false;
  }

  boolean press(float px, float py) {
    if (over(px, py)) return selected=true;
    return selected=false;
  }

  boolean release(float px, float py) {
    if (selected) return !(selected=false);
    return false;
  }
}
1 Like

That’s beautiful. Thank you.

I’m new at classes but it seems clean, I’ll look deeper.

1 Like