We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpPrograms › Scatter plot with 'buttons'
Page Index Toggle Pages: 1
Scatter plot with 'buttons' (Read 1456 times)
Scatter plot with 'buttons'
Apr 2nd, 2010, 10:58am
 
Hi everyone,

I'm writing a simple scatterplot and would like a bit of help with creating some buttons (maybe an array?).

At the moment the plot displays fine and hovering over each point gives you a label.  I am trying to find a way to make the label display permenantly when you click each point (and turn off if clicked again obviously).

At the moment I'm using a simple .csv with fake data in it:

Name, Use, Useful
cat, 0.43, 0.65
bat, 0.23, 0.28
dog, 0.15, 0.75
pidgeon, 0.85, 0.61

If anyone could help I would really appreciate it.

Thanks

Code:
float xPerc;
float yPerc;
int back;
int plaice;
int chartSize;

void setup(){

 back = 400;
 size(back,back);
 background (200);
 smooth();
}

void draw(){
 background (200);
 noStroke();

 plaice = 10;
 chartSize = back-plaice*2;

 fill(255);
 rect(plaice, plaice, chartSize, chartSize);
 stroke(200);
 for (int i=0; i<=3; i++){
   line(plaice+(i*(chartSize/4)), plaice, plaice+(i*(chartSize/4)), plaice+chartSize);
   line(plaice, plaice+chartSize-(i*(chartSize/4)), plaice+chartSize, plaice+chartSize-(i*(chartSize/4)));
 }

 String[] data = loadStrings("fakeDat.csv");
 for (int i=1; i < data.length; i++){
   String[] name = split(data[i],",");
   float[] vals = float(split(data[i],","));
   //println(vals[1]);
   xPerc = vals[1];
   yPerc = vals[2];
   float dotCol1 = map(vals[1],0,1,0,255);
   float dotCol2 = map(vals[2],0,1,0,255);
   fill(dotCol1, dotCol2, 200);

   stroke(100);
   ellipse(plaice+(xPerc*chartSize),(plaice+chartSize)-(yPerc*chartSize), 10, 10);
   fill(0);
   if(mouseX > plaice+(xPerc*chartSize)-10 && mouseX < plaice+(xPerc*chartSize)+10 && mouseY >
     (plaice+chartSize)-(yPerc*chartSize)-10 && mouseY < (plaice+chartSize)-(yPerc*chartSize) +10)
   {
     text (name[0],(plaice+(xPerc*chartSize))+10,(plaice+chartSize)-(yPerc*chartSize));
   }
 }
}


Re: Scatter plot with 'buttons'
Reply #1 - Apr 2nd, 2010, 7:01pm
 
Some people use the ControlP5 library to make such buttons...
http://www.sojamo.de/libraries/controlP5/

The other option is to write your own button class.  I am writing up an example of this; it might be useful for others too...
Re: Scatter plot with 'buttons'
Reply #2 - Apr 2nd, 2010, 7:05pm
 
First of all, I think that you should re-consider stuff in a more Object-Oriented programming way. I took the time to rewrite some of your code implementing an object for each record(field):

Code:
float xPerc;
float yPerc;
int back;
int plaice;
int chartSize;

ArrayList fields = new ArrayList();
ArrayList activeFields = new ArrayList();

void setup(){

back = 400;
size(back,back);
background (200);
smooth();
importData();
}

void importData() {
String[] data = loadStrings("fakeDat.csv");
for (int i=0; i < data.length; i++){ //Start from zero, not one
String[] temp=split(data[i],",");
fields.add(new field(temp[0],float(temp[1]),float(temp[2])));
}
}

class field {
String name;
float x,y;
field(String namein,float xin,float yin) {
name=namein;
x=xin;
y=yin;
}
}

void draw(){
background (200);
noStroke();

plaice = 10;
chartSize = back-plaice*2;

fill(255);
rect(plaice, plaice, chartSize, chartSize);
stroke(200);
for (int i=0; i<=3; i++){
line(plaice+(i*(chartSize/4)), plaice, plaice+(i*(chartSize/4)), plaice+chartSize);
line(plaice, plaice+chartSize-(i*(chartSize/4)), plaice+chartSize, plaice+chartSize-(i*(chartSize/4)));
}

for (int i=0; i < fields.size(); i++){
field f=(field)fields.get(i);
float dotCol1 = map(f.x,0,1,0,255);
float dotCol2 = map(f.y,0,1,0,255);
fill(dotCol1, dotCol2, 200);

stroke(100);
ellipse(plaice+(f.x*chartSize),(plaice+chartSize)-(f.y*chartSize), 10, 10);
fill(0);
if(mouseX > plaice+(f.x*chartSize)-10 && mouseX < plaice+(f.x*chartSize)+10 && mouseY >
(plaice+chartSize)-(f.y*chartSize)-10 && mouseY < (plaice+chartSize)-(f.y*chartSize) +10)
{
text (f.name,(plaice+(f.x*chartSize))+10,(plaice+chartSize)-(f.y*chartSize));
}
}
}


I trust that this will help you in achieving the permanent label display. What you should do is check in the mousePressed() event if a point is under the cursor. If it is, copy it to the activePoints ArrayList. If it is in the activePoints already (check with ArrayList.contains(x)), then remove it (click-again behavior). Then just render the labels of the items present in this ArrayList, apart from anything else you normally render.
Re: Scatter plot with 'buttons'
Reply #3 - Apr 2nd, 2010, 7:19pm
 
This could mesh nicely with the above advice:

Quote:
button[] buttons = new button[4];
PFont myFont;

void setup(){
  size(500,200);
  buttons[0] = new button(100,100,"Trout");
  buttons[1] = new button(200,100,"Lobster");
  buttons[2] = new button(300,100,"Eel");
  buttons[3] = new button(400,100,"Goat");
  rectMode(CENTER); // for nice centered buttons
  textAlign(CENTER,CENTER); // with nice centered text
  myFont=createFont("Courier New", 16); // can be changed to loadFont if you have a .vlw file
  textFont(myFont,16);
}

void draw(){
  background(75);
  // each frame, update all the buttons:
  for (int i=0;i<buttons.length;i++){
    buttons[i].update();
  }
}

class button{  // declare the class
  // these variables belong to the button class:>
  float xpos,ypos,w,h;
  String myText;
  boolean showText;
  // this is the "constructor" section, where the new button receives
  // variables passed from setup() (in this case) and assigns them appropriately:
  button(float passX, float passY, String passText){
    xpos=passX;
    ypos=passY;
    myText=passText;
    w=76; // for now, all buttons have the same dimensions.
    h=30;
  }
  // and everything that follows are the functions of the button class:
  void update(){
    if (mouseWithin()){ // the mouse is within the area of the button, so:
      if (mousePressed) fill(220,220,255); // color the button bright blue if the mouse is pressed...
      else fill(150,150,255); // or just blue if the mouse is hovering.
    }
    else fill(175); // otherwise color the rectangle grey.
    rect(xpos,ypos,w,h); // draw the button
    if ((showText) || (mouseWithin())){ // if showText is true, or the mouse is hovering,
      // display the text:
      fill(0);
      text(myText,xpos,ypos);
    }
  }
  void click(){ // this function is run when the button is clicked.
    showText=!showText; // in this case, all we want is for it to toggle the "showText" boolean.
  }
  boolean mouseWithin(){
    return ((mouseX>xpos-w/2) && (mouseX<xpos+w/2) && (mouseY>ypos-h/2) && (mouseY<ypos+w/2));
    // this boolean function returns True if the mouse is within the button area,
    // and False if not.
  }
}

void mousePressed(){
  for (int i=0;i<buttons.length;i++){
    if (buttons[i].mouseWithin()){
      buttons[i].click(); // trigger that button's "click" function
      break; // break the loop in order to stop checking buttons, so that when you
      // click an area of two overlapping buttons, only the top button gets triggered.
    }
  }
}

Re: Scatter plot with 'buttons'
Reply #4 - Apr 3rd, 2010, 3:14am
 
Thanks very much to both of you.

There's plenty of stuff in those examples that I haven't seen before so I'm going to sit down and work through them step by step.

I've never thought of writing a class to hold values which then feeds into an array - that will probably solve a number of problems I've been stuck with.

The buttons do just what i wanted so maybe plotting buttons instead of 'points' will work as well.

I'll work on this some more and see what happens.

Thanks again
Page Index Toggle Pages: 1