Hi all,
I’m trying to represent a very basic 1-column table as a bar chart. The .csv file reads as follows:
Value
50
100
150
200
250
300
350
400
450
500
My problem is I can’t manage to display each value on top of the bar when hovering over it. All values display at once and can’t figure out the algorithm for mouseX,Y. Below the code:
Bar[] bars;
//the data from the table will fill the array
Table table;
void setup() {
size(500,500,P2D);
loadData();
}
void draw() {
background(255);
//display all bars
for(int i = 0; i < bars.length; i++) {
bars[i].display();
bars[i].rollover();
}
}
void loadData() {
//load file into table; header indicates the file has a non-data 1st row
table = loadTable("data.csv", "header");
//the size of the array is determined by the number of rows in the table
bars = new Bar[table.getRowCount()];
for(int i = 0; i < table.getRowCount(); i++) {
TableRow row = table.getRow(i); //iterate over all the table rows
//access the fields via their table names
float Val = row.getInt("Value");
//make a rectangle out of the data from each row
float x = 50*i;
bars[i] = new Bar(x,Val);
}
}
class Bar {
float x;
float Val;
//by default the mouse is not over the bar
boolean inside = false;
//Create the bar
Bar(float tempX, float tempVal) {
x = tempX;
Val = tempVal;
}
//Checking if mouse is within the bar
void rollover() {
for(int i = 0; i < table.getRowCount(); i++) {
if(mouseX > x && mouseX < x+50 && mouseY > height - table.getInt(i,0)) {
inside = true;
} else {
inside = false;
}
}
}
//Display the bar
void display() {
stroke(255);
fill(0);
for(int i = 0; i < table.getRowCount(); i++) {
rect(50*i,height,50,-table.getInt(i,0));
}
if(inside) {
fill(255,0,0);
textSize(10);
textAlign(CENTER);
for(int i = 0; i < table.getRowCount(); i++) {
text(int(table.getInt(i,0)),25+50*i,height/2);
}
}
}
}
Thanks @mnse! That was espectacular, and much simpler than my solution.
Now I’m trying to extrapolate the same code by loading a different table in which I’m only using the 3rd column (Data_value) as the bar heights (divided by 1000 to fit in 500x500px):
The problem I’m finding when rendering is that some column widths look weird. Suspect that might be because of floating numbers? but I’ve tried to convert column width to integer to no avail.
Bar[] bars;
//the data from the table will fill the array
Table table;
void setup() {
size(500,500,P2D);
textSize(15);
textAlign(CENTER);
loadData();
}
void draw() {
background(255);
//display all rectangles
for(int i = 0; i < bars.length; i++) {
bars[i].display();
bars[i].rollover();
}
}
void loadData() {
//load file into table; header indicates the file has a non-data 1st row
table = loadTable("business-employment-data-mar-2022-quarter-AFF.csv", "header");
//the size of the array is determined by the number of rows in the table
bars = new Bar[table.getRowCount()];
for(int i = 0; i < table.getRowCount(); i++) {
//defining bar width
float w = width/table.getRowCount();
//make a rectangle out of the data from each row
bars[i] = new Bar(w*i,w,table.getRow(i).getFloat("Data_value")/1000);
}
}
class Bar {
float x;
float w;
float Val;
boolean inside; //determine if the mouse is within the bar
//Create the bar
Bar(float tempX, float tempW, float tempVal) {
x = tempX;
w = tempW;
Val = tempVal;
inside = false; //by default the mouse is not within the bar
}
//Checking if mouse if over the bar
void rollover() {
if(mouseX > x && mouseX < x+w && mouseY > height - Val) {
inside = true;
} else {
inside = false;
}
}
//Display the bar
void display() {
stroke(255);
fill(0);
rect(x,height-Val,x+w,Val);
if(inside) {
fill(255,0,0);
text(int(Val*1000),x+w/2,height-Val-10);
}
}
}
rectMode(CORNERS) interprets the first two parameters of rect() as the location of one corner, and the third and fourth parameters as the location of the opposite corner.