codetoad.com
  ASP Shopping CartForum & BBS
  - all for $20 from CodeToad Plus!
  
  Home || ASP | ASP.Net | C++/C# | DHTML | HTML | Java | Javascript | Perl | VB | XML || CodeToad Plus! || Forums || RAM 
Search Site:
Search Forums:
  bar graphs again with seperate class  masterchief at 20:17 on Sunday, February 18, 2007
 

hey everyone again:

for my bar graphs, i need tot use a class to create all the bars, but there is another class calling all of these methods.

These methods are:
the constructor

public void setValuesAndLabels(double []values, String []labels, int nbr)
public int getCurrentBar(int value)
public void setCurrentBar(int value)
public int getNbrBars()
public int getMaxBars()
public double getBarValue(int idx
public void setBarValue(int idx, double value)
public String getBarLabel(int idx)
public void setBarLabel(int idx, String value)
public void addBar(double val, String lbl)
public void paintComponent(Graphics g)
public Boolean addBarChartListener(BarChartListener b)

that example given before was great, but i am having trouble understanding how i can apply that information into methods like these. Can someone please help me?

-MAster Chief will save us all-

  Re: bar graphs again with seperate class  crwood at 08:03 on Monday, February 19, 2007
 

Here's a suggestion. You can keep the BarChart model separate from the view (the rendering of the chart) and the event code. MVC = model view controller.

import java.awt.*;
import java.awt.event.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.text.NumberFormat;
import javax.swing.*;
import javax.swing.event.*;

public class BarModelTest {
BarChartModel chartModel = new BarChartModel();
BarChartPanel chartPanel = new BarChartPanel();
JSpinner barSpinner;
JSpinner heightSpinner;
NumberFormat nf;

public BarModelTest() {
nf = NumberFormat.getInstance();
nf.setMaximumFractionDigits(1);
double[] values = { 19.7, 47.2, 32.4 };
int n = values.length;
String[] labels = new String[n];
for(int j = 0; j < n; j++)
labels[j] = nf.format(values[j]);
chartModel.setValuesAndLabels(values, labels, n);
chartPanel.setDataAndLabels(values, labels);
chartPanel.setSelection(chartModel.getCurrentBar());
}

private Box getUIPanel() {
int bar = chartModel.getCurrentBar() +1;
int nbr = chartModel.getNbrBars();
SpinnerNumberModel barModel = new SpinnerNumberModel(bar,1,nbr,1);
barSpinner = new JSpinner(barModel);
double val = chartModel.getBarValue(chartModel.getCurrentBar());
SpinnerNumberModel heightModel = new SpinnerNumberModel(val,10.0,100.0,0.1);
heightSpinner = new JSpinner(heightModel);
int bars = chartModel.getNbrBars();
int max = chartModel.getMaxBars();
SpinnerNumberModel sizeModel = new SpinnerNumberModel(bars,1,max,1);
final JSpinner sizeSpinner = new JSpinner(sizeModel);
ChangeListener cl = new ChangeListener() {
public void stateChanged(ChangeEvent e) {
JSpinner spinner = (JSpinner)e.getSource();
Number value = (Number)spinner.getValue();
if(spinner == barSpinner) {
int index = value.intValue() -1;
chartModel.setCurrentBar(index);
heightSpinner.setValue(chartModel.getBarValue(index));
chartPanel.setSelection(index);
}
if(spinner == heightSpinner) {
int selected = chartModel.getCurrentBar();
double barVal = value.doubleValue();
String label = nf.format(barVal);
chartModel.setBarValue(selected, barVal);
chartModel.setBarLabel(selected, label);
chartPanel.setValueAndLabel(selected, barVal, label);
}
if(spinner == sizeSpinner) {
int val = value.intValue();
SpinnerNumberModel model = (SpinnerNumberModel)barSpinner.getModel();
model.setMaximum(val);
if(model.getNumber().intValue() > val)
model.setValue(value);
if(val > chartModel.getNbrBars()) {
double height = ((Number)heightSpinner.getValue()).doubleValue();
chartModel.addBar(height, nf.format(height));
} else if(val < chartModel.getNbrBars()) {
chartModel.removeBar();
}
chartPanel.setDataAndLabels(chartModel.values, chartModel.labels);
}
}
};
barSpinner.addChangeListener(cl);
heightSpinner.addChangeListener(cl);
sizeSpinner.addChangeListener(cl);
Box box = Box.createHorizontalBox();
box.add(Box.createHorizontalGlue());
box.add(new JLabel("bar"));
box.add(barSpinner);
box.add(Box.createHorizontalGlue());
box.add(new JLabel("cell height"));
box.add(heightSpinner);
box.add(Box.createHorizontalGlue());
box.add(new JLabel("bars"));
box.add(sizeSpinner);
box.add(Box.createHorizontalGlue());
return box;
}

public static void main(String[] args) {
BarModelTest test = new BarModelTest();
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(test.chartPanel);
f.getContentPane().add(test.getUIPanel(), "Last");
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}

class BarChartPanel extends JPanel {
double[] data = new double[0];
String[] labels = new String[0];
AffineTransform at;
double maxValue;
int selectedBar = -1;
final int SPAD = 30;
final int PAD = 20;

public void setValueAndLabel(int index, double value, String label) {
data[index] = value;
labels[index] = label;
// if value exceeds top of ordinate -> rescale
if(value > maxValue) {
maxValue = value;
if(at != null)
at = null;
}
repaint();
}

public void setDataAndLabels(double[] values, String[] labels) {
data = values;
this.labels = labels;
// new data -> rescale all data
double max = getDataMax();
if(Math.abs(max - maxValue) > 1.0) {
maxValue = max;
if(at != null)
at = null;
}
repaint();
}

public void setSelection(int index) {
selectedBar = index;
repaint();
}

protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
double w = getWidth();
double h = getHeight();
double xInc = (w-2*PAD)/data.length;
if(at == null)
initTransform();
g2.setPaint(new Color(51,51,51));
// ordinate
g2.draw(new Line2D.Double(PAD, PAD, PAD, h-PAD));
// abcissa
g2.draw(new Line2D.Double(PAD, h-PAD, w-PAD, h-PAD));
// draw labels
Color color = g2.getColor();
Color selectedColor = Color.red;
Font font = g2.getFont().deriveFont(14f);
g2.setFont(font);
FontRenderContext frc = g2.getFontRenderContext();
for(int j = 0; j < labels.length; j++) {
float width =(float)font.getStringBounds(labels[j], frc).getWidth();
LineMetrics lm = font.getLineMetrics(labels[j], frc);
float height = lm.getHeight();
float sx = (float)(PAD + j*xInc + (xInc - width)/2);
float sy = (float)(h-SPAD + (height+SPAD)/2);
// show selection
g2.setPaint((j == selectedBar) ? selectedColor : color);
g2.drawString(labels[j], sx, sy);
}
// plot data
g2.setPaint(Color.blue);
double x = PAD, lastY;
double zero = modelToView(0);
for(int j = 0; j < data.length; j++) {
double y = modelToView(data[j]);
g2.draw(new Line2D.Double(x, y, x+xInc, y));
if(j > 0) {
if(data[j-1] < data[j])
g2.draw(new Line2D.Double(x, y, x, zero));
if(j < data.length-1 && data[j+1] <= data[j])
g2.draw(new Line2D.Double(x+xInc, y, x+xInc, zero));
} else if(j == 0 && data.length > 1 && data[0] >= data[1]) {
g2.draw(new Line2D.Double(x+xInc, y, x+xInc, zero));
}
if(j == data.length-1) {
// last bar, close
g2.draw(new Line2D.Double(x+xInc, y, x+xInc, zero));
}
x += xInc;
lastY = y;
}
}

public Dimension getPreferredSize() {
return new Dimension(400,400);
}

private double modelToView(double y) {
Point2D.Double dest = new Point2D.Double();
Point2D.Double src = new Point2D.Double(0, y);
at.transform(src, dest);
return dest.y;
}

private void initTransform() {
double w = getWidth();
double h = getHeight();
double maxY = getDataMax();
double xScale = (w-2*PAD)/data.length;
double yScale = (h-2*PAD)/maxY;
// move to origin
double x = PAD;
double y = h-PAD;
at = AffineTransform.getTranslateInstance(x,y);
// scale and flip(-) about the abcissa
at.scale(xScale, -yScale);
}

private double getDataMax() {
double max = Double.MIN_VALUE;
for(int j = 0; j < data.length; j++) {
if(data[j] > max)
max = data[j];
}
return max;
}
}

class BarChartModel {
double[] values = new double[0];
String[] labels = new String[0];
int currentBar = 0;
int numBars = 0;
int MAX_BARS = 5;

public void setValuesAndLabels(double[] values, String[] labels, int nbr) {
this.values = values;
this.labels = labels;
numBars = nbr;
}

public int getCurrentBar() {
return currentBar;
}

public void setCurrentBar(int value) {
currentBar = value;
}

public int getNbrBars() {
return numBars;
}

public int getMaxBars() {
return MAX_BARS;
}

public double getBarValue(int idx) {
return values[idx];
}

public void setBarValue(int idx, double value) {
values[idx] = value;
}

public String getBarLabel(int idx) {
return labels[idx];
}

public void setBarLabel(int idx, String value) {
labels[idx] = value;
}

public void addBar(double val, String lbl) {
addValue(val);
addLabel(lbl);
numBars = values.length;
}

public void removeBar() {
// remove currentBar
numBars--;
double[] tempValues = new double[numBars];
String[] tempLabels = new String[numBars];
for(int j = 0, k = 0; j < values.length; j++) {
if(j == currentBar) {
continue;
} else {
tempValues[k] = values[j];
tempLabels[k++] = labels[j];
}
}
values = tempValues;
labels = tempLabels;
}

private void addValue(double value) {
double[] temp = new double[numBars+1];
System.arraycopy(values, 0, temp, 0, numBars);
temp[numBars] = value;
values = temp;
}

private void addLabel(String label) {
String[] temp = new String[numBars+1];
System.arraycopy(labels, 0, temp, 0, numBars);
temp[numBars] = label;
labels = temp;
}
}


  Re: bar graphs again with seperate class  masterchief at 11:08 on Monday, February 19, 2007
 

Thanks again for the help, but i cant use the Jspinner, numberformat, affinetransform because I dont know how to use those. I really only know basic coding, not the advance coding that you are showing me right now.

I am pretty much just using the rectangle class and mouse listeners to do what i have to do. Is there another way?




  Re: bar graphs again with seperate class  crwood at 20:10 on Monday, February 19, 2007
 

Here's a simpler bar chart without java input components, AffineTransform or NumberFormat.
You can select and drag the bars with the mouse. Your list of methods would most likely go in the BarChart class which is now both graphics component and model. Without input components/widgets I'm not sure how you will change the number of bars. In case you change your mind about using input components, here's a link to what's available in Swing: A Visual Index to the Swing Components. Moving up–directory will reveal other pages on potentially useful subjects such as component layout and writing event listeners.

import java.awt.*;
import java.awt.event.*;
import java.awt.font.*;
import javax.swing.*;
import javax.swing.event.MouseInputAdapter;

public class BarChart extends JPanel {
double[] data;
Rectangle[] bars;
int selectedIndex = -1;
double maxValue = 100.0;
int BAR_SPACE = 15;
int PAD = 20;

public BarChart(double[] data) {
this.data = data;
}

public void setSelection(int index) {
selectedIndex = index;
repaint();
}

public void setBar(int index, int y) {
int x = bars[index].x;
int w = bars[index].width;
int h = bars[index].height - (y - bars[index].y);
bars[index].setRect(x, y, w, h);
resetValue(index);
repaint();
}

protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
int w = getWidth();
int h = getHeight();
int x0 = PAD;
int y0 = h - PAD;
if(bars == null)
initBars(w, h, x0, y0);
// bars
g2.setPaint(Color.blue);
for(int j = 0; j < bars.length; j++) {
if(j == selectedIndex) {
Color color = g2.getColor();
g2.setPaint(new Color(240,240,220));
g2.fill(bars[j]);
g2.setPaint(color);
}
g2.draw(bars[j]);
}
g2.setPaint(Color.black);
// abcissa
g2.drawLine(x0, y0, w-PAD, y0);
// ordinate
g2.drawLine(x0, PAD, x0, y0);
// label bars
Font font = g2.getFont().deriveFont(16f);
g2.setFont(font);
FontRenderContext frc = g2.getFontRenderContext();
for(int j = 0; j < bars.length; j++) {
String s = format(data[j]);
float width = (float)font.getStringBounds(s, frc).getWidth();
LineMetrics lm = font.getLineMetrics(s, frc);
float x = bars[j].x + (bars[j].width- width)/2;
float y = bars[j].y - lm.getDescent();
g2.drawString(s, x, y);
}
}

private void initBars(int w, int h, int x0, int y0) {
bars = new Rectangle[data.length];
int barWidth = (w - 2*PAD - (bars.length+1)*BAR_SPACE)/bars.length;
double scale = (h - 2*PAD)/maxValue;
for(int j = 0; j < bars.length; j++) {
int x = x0 + BAR_SPACE + j*(barWidth + BAR_SPACE);
int height = (int)(scale * data[j]);
int y = y0 - height;
bars[j] = new Rectangle(x, y, barWidth, height);
}
}

private void resetValue(int index) {
// scale could be made a member variable.
double scale = (getHeight() - 2*PAD)/maxValue;
data[index] = bars[index].height/scale;
}

private String format(double value) {
int n = (int)(value*10);
return String.valueOf(((double)n)/10.0);
}

public Dimension getPreferredSize() {
return new Dimension(400,400);
}

public static void main(String[] args) {
double[] data = { 34.2, 16.9, 44.3, 75.6 };
BarChart barChart = new BarChart(data);
BarController controller = new BarController(barChart);
barChart.addMouseListener(controller);
barChart.addMouseMotionListener(controller);
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(barChart);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}

class BarController extends MouseInputAdapter {
BarChart barChart;
Cursor defaultCursor = Cursor.getDefaultCursor();
Cursor moveCursor = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);
boolean dragging = false;
int selectedIndex = -1;
int offsetY;

public BarController(BarChart bc) {
barChart = bc;
}

public void mousePressed(MouseEvent e) {
Point p = e.getPoint();
Rectangle[] rects = barChart.bars;
if(selectedIndex == -1) {
// Are we selecting a bar?
for(int j = 0; j < rects.length; j++) {
if(rects[j].contains(p)) {
selectedIndex = j;
barChart.setCursor(moveCursor);
barChart.setSelection(j);
break;
}
}
} else {
// Or, do we want to drag a bar?
offsetY = p.y - rects[selectedIndex].y;
dragging = true;
}
}

public void mouseReleased(MouseEvent e) {
if(dragging) {
dragging = false;
selectedIndex = -1;
barChart.setSelection(selectedIndex);
barChart.setCursor(defaultCursor);
}
}

public void mouseDragged(MouseEvent e) {
if(dragging) {
int y = e.getY() - offsetY;
barChart.setBar(selectedIndex, y);
}
}

public void mouseMoved(MouseEvent e) {
Point p = e.getPoint();
Rectangle[] rects = barChart.bars;
boolean hovering = false;
if(selectedIndex != -1) {
if(rects[selectedIndex].contains(p)) {
hovering = true;
if(barChart.getCursor() == defaultCursor)
barChart.setCursor(moveCursor);
}
}
if(!hovering && barChart.getCursor() == moveCursor)
barChart.setCursor(defaultCursor);
}
}









CodeToad Experts

Can't find the answer?
Our Site experts are answering questions for free in the CodeToad forums
//








Recent Forum Threads
•  How to send multiple perameters in SOAP request.
•  Java code for Insert picture on the table in spreadsheet
•  Re: Problem with concatenation
•  how to genrates the crystal report by sending a id at runtime
•  help me
•  pls help me with this..
•  Re: Security - Code verify
•  Job @ EarlySail
•  Job @ EarlySail (perl)


Recent Articles
ASP GetTempName
Decode and Encode UTF-8
ASP GetFile
ASP FolderExists
ASP FileExists
ASP OpenTextFile
ASP FilesystemObject
ASP CreateFolder
ASP CreateTextFile
Javascript Get Selected Text


© Copyright codetoad.com 2001-2007