Simple TrackBar for Processing

Example

Hello. I've in the past wanted a simple trackbar to get values from so I can easily change values for testing while running the program. Yesterday I had a dream about using one to change the frequency of a sin wave and it looked really cool so I worked on one for a few hours :P Hope it can be useful maybe at some time. If other people want to improve it since it is pretty fragile feel free to :

/** 
   Author : Dinoswarleafs (twitter.com/Dinoswarleafs) 
   Simple input on a slider like a TrackBar on Visual Studio

   Parameters/Constructor :
   TrackBar(a, b, c, d, e, f)

   a = x-coordinate of bar
   b = y-coordinate of bar
   c = length of bar
   d = value of first tick
   e = value of last tick
   f = value between ticks (1 = 1, 2, 3, 4 | 2 = 1, 3, 5, 7 ...)

   Draw Loop :
   (name).update();
   (name).display();

   Get Slider's Value :
   (name).selectedValue (is float)

   Other customizations :
   There are a few things I just put in since they seemed too trivial to put in the constructor

   Change circle selector size    - cSize = new PVector(x, y)
   Change height of ticks         - tickHeight = y
   Change colors (display())      - fill(color)
   Text on ticks (display())      - uncomment text(...) in for loop
   Text on side ticks (display()) - uncomment 2 text(...) lines after foor loop


   To Do: 
    - Exemption Handling
    - Scaling/Resizing
    - Prettier Bar?
*/

class TrackBar {

  ArrayList<PVector> indexes = new ArrayList<PVector>();
  PVector startPos, endPos, sideValues, sCircle, cSize;
  float increment, range, indexRange, gapLength, tickHeight, selectedValue;
  boolean isActivated;

  TrackBar(float startX, float startY, float xLength, float startValue, float endValue, float increment_) {
    startPos       = new PVector(startX, startY);
    endPos         = new PVector(startX + xLength, startY);
    sideValues     = new PVector(startValue, endValue);
    sCircle        = new PVector(startX, startY);
    cSize          = new PVector(20, 20);
    increment      = increment_;
    range          = endPos.x - startPos.x;
    if (sideValues.x == 0 || sideValues.y == 0)
     indexRange    = (abs(sideValues.x - sideValues.y) + 1) / increment;
    else
     indexRange    = abs(sideValues.x - sideValues.y) / increment; 
    gapLength      = range / indexRange;
    tickHeight     = 20;
    selectedValue  = sideValues.x; 

    float value = sideValues.x;
    float i = startPos.x;
    for (; i < endPos.x; i += gapLength) {
     indexes.add(new PVector(value, i));
     value += increment;
    }
    indexes.add(new PVector(sideValues.y, i));
  }

  void update() {
   int closestIndex = closestIndex();
   selectedValue = indexes.get(closestIndex).x;
   if (mousePressed && clickedCircle()) 
    isActivated = true;
   if (isActivated && mousePressed)
    //if (startPos.x < mouseX && mouseX < endPos.x)
     sCircle.x = mouseX;
   else {
    isActivated = false;
    sCircle.x = indexes.get(closestIndex).y;
   }
  }

  void display() {
    stroke(200);
    strokeWeight(2);
    fill(255);
    line(startPos.x, startPos.y, endPos.x, endPos.y);
    textAlign(CENTER);
    for (int i = 0; i < indexes.size(); i++) {
     line(indexes.get(i).y, startPos.y + tickHeight, indexes.get(i).y, startPos.y - tickHeight);
     //text((int) indexes.get(i).x, indexes.get(i).y, startPos.y + (tickHeight * 2));
    }
    text((int) indexes.get(0).x, indexes.get(0).y, startPos.y + (tickHeight * 2));
    text((int) indexes.get(indexes.size() - 1).x, indexes.get(indexes.size() - 1).y, startPos.y + (tickHeight * 2));
    fill(255);
    noStroke();
    ellipse(sCircle.x, sCircle.y, cSize.x, cSize.y);
  }


  boolean overButton() {
   // Checks if the mouse is within the circle
   // Source : https://processing.org/examples/button.html
   float disX = sCircle.x - mouseX; 
   float disY = sCircle.y - mouseY; 
   return (sqrt(sq(disX) + sq(disY))) < cSize.x/2;
  }

  boolean clickedCircle() {
   return overButton() && mousePressed; 
  }

  int closestIndex() {
   for (int i = 0; i < indexes.size(); i++)
    if (sCircle.x < startPos.x)
     return 0;
    else if (sCircle.x > endPos.x)
     return indexes.size() - 1;
    else if (abs(sCircle.x - indexes.get(i).y) < gapLength / 2) {
     return i;
    }
    println("No closest index! This shouldn't be possible unless you modified & broke the code.");
    return -1;
  }
}

It's in my tool repo along with my button class if you want to use that (I didn't comment that one at all: https://github.com/Dinoswarleafs/DinoTools/tree/master/Tools

Tagged:

Comments

  • Thxs for sharing. Don't forget to include an example showcasing your code. For people to be able to copy and paste and run your code to see what it does, or to see your features will make them more incline to use it or even provide suggestions. You could even include a screenshot or for advanced features, a very short clip.

    Kf

  • edited July 2017

    Thanks :) Added

    Is there anyway to embed a GIF onto the processing forums?

Sign In or Register to comment.