skip to Main Content

I’m trying to create a custom dynamic histogram type bar graph in Java. I’ve searched a lot but coudn’t find a way to achieve this.

I’m aware of the JFreeChart library but it doesn’t meet my needs. This is what the JFreeChart histogram looks like :

enter image description here

But what I want is a dyanamic Histogram with just X-axis.
This photoshopped image will make it easier to understand.
enter image description here

The JFrame will have fixed boundaries. As you can see, there should be no Y-axis. The bars’ height should adjust automatically based on the values.

Please help me build this! Thanks in advance.

2

Answers


  1. I’d give JFreeChart a second look. You can make the range axis invisible and use item labels instead. Absent a legend, overriding getItemPaint() can supply arbitrary colors. An alternative approach is shown here.

    image

    import java.awt.Color;
    import java.awt.EventQueue;
    import java.awt.Paint;
    import javax.swing.JFrame;
    import org.jfree.chart.ChartPanel;
    import org.jfree.chart.JFreeChart;
    import org.jfree.chart.axis.CategoryAxis;
    import org.jfree.chart.axis.NumberAxis;
    import org.jfree.chart.axis.ValueAxis;
    import org.jfree.chart.labels.ItemLabelAnchor;
    import org.jfree.chart.labels.ItemLabelPosition;
    import org.jfree.chart.labels.StandardCategoryItemLabelGenerator;
    import org.jfree.chart.plot.CategoryPlot;
    import org.jfree.chart.renderer.category.BarRenderer;
    import org.jfree.chart.renderer.category.StandardBarPainter;
    import org.jfree.data.category.CategoryDataset;
    import org.jfree.data.category.DefaultCategoryDataset;
    import org.jfree.ui.TextAnchor;
    
    /**
     * @see https://stackoverflow.com/a/29709153/230513
     */
    public class BarChart {
    
        private CategoryDataset createDataset() {
            String row = "Row";
            DefaultCategoryDataset dataset = new DefaultCategoryDataset();
            dataset.addValue(350, row, "A");
            dataset.addValue(690, row, "B");
            dataset.addValue(510, row, "C");
            dataset.addValue(570, row, "D");
            dataset.addValue(180, row, "E");
            dataset.addValue(504, row, "F");
            return dataset;
        }
    
        private JFreeChart createChart(CategoryDataset dataset) {
            CategoryAxis categoryAxis = new CategoryAxis("");
            ValueAxis valueAxis = new NumberAxis("");
            valueAxis.setVisible(false);
            BarRenderer renderer = new BarRenderer() {
    
                @Override
                public Paint getItemPaint(int row, int column) {
                    switch (column) {
                        case 0:
                            return Color.red;
                        case 1:
                            return Color.yellow;
                        case 2:
                            return Color.blue;
                        case 3:
                            return Color.orange;
                        case 4:
                            return Color.gray;
                        case 5:
                            return Color.green.darker();
                        default:
                            return Color.red;
                    }
                }
            };
            renderer.setDrawBarOutline(false);
            renderer.setBaseItemLabelGenerator(new StandardCategoryItemLabelGenerator());
            renderer.setBasePositiveItemLabelPosition(new ItemLabelPosition(
                ItemLabelAnchor.OUTSIDE12, TextAnchor.BOTTOM_CENTER));
            renderer.setBaseItemLabelsVisible(Boolean.TRUE);
            renderer.setBarPainter(new StandardBarPainter());
            CategoryPlot plot = new CategoryPlot(dataset, categoryAxis, valueAxis, renderer);
            JFreeChart chart = new JFreeChart("", JFreeChart.DEFAULT_TITLE_FONT, plot, false);
            chart.setBackgroundPaint(Color.white);
            return chart;
        }
    
        private void display() {
            JFrame f = new JFrame("BarChart");
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.add(new ChartPanel(createChart(createDataset())));
            f.pack();
            f.setLocationRelativeTo(null);
            f.setVisible(true);
        }
    
        public static void main(String[] args) {
            EventQueue.invokeLater(() -> {
                new BarChart().display();
            });
        }
    }
    
    Login or Signup to reply.
  2. A poor man’s histogram:

    enter image description here

    import java.awt.*;
    import java.util.List;
    import java.util.ArrayList;
    import javax.swing.*;
    import javax.swing.border.*;
    
    public class HistogramPanel extends JPanel
    {
        private int histogramHeight = 200;
        private int barWidth = 50;
        private int barGap = 10;
    
        private JPanel barPanel;
        private JPanel labelPanel;
    
        private List<Bar> bars = new ArrayList<Bar>();
    
        public HistogramPanel()
        {
            setBorder( new EmptyBorder(10, 10, 10, 10) );
            setLayout( new BorderLayout() );
    
            barPanel = new JPanel( new GridLayout(1, 0, barGap, 0) );
            Border outer = new MatteBorder(1, 1, 1, 1, Color.BLACK);
            Border inner = new EmptyBorder(10, 10, 0, 10);
            Border compound = new CompoundBorder(outer, inner);
            barPanel.setBorder( compound );
    
            labelPanel = new JPanel( new GridLayout(1, 0, barGap, 0) );
            labelPanel.setBorder( new EmptyBorder(5, 10, 0, 10) );
    
            add(barPanel, BorderLayout.CENTER);
            add(labelPanel, BorderLayout.PAGE_END);
        }
    
        public void addHistogramColumn(String label, int value, Color color)
        {
            Bar bar = new Bar(label, value, color);
            bars.add( bar );
        }
    
        public void layoutHistogram()
        {
            barPanel.removeAll();
            labelPanel.removeAll();
    
            int maxValue = 0;
    
            for (Bar bar: bars)
                maxValue = Math.max(maxValue, bar.getValue());
    
            for (Bar bar: bars)
            {
                JLabel label = new JLabel(bar.getValue() + "");
                label.setHorizontalTextPosition(JLabel.CENTER);
                label.setHorizontalAlignment(JLabel.CENTER);
                label.setVerticalTextPosition(JLabel.TOP);
                label.setVerticalAlignment(JLabel.BOTTOM);
                int barHeight = (bar.getValue() * histogramHeight) / maxValue;
                Icon icon = new ColorIcon(bar.getColor(), barWidth, barHeight);
                label.setIcon( icon );
                barPanel.add( label );
    
                JLabel barLabel = new JLabel( bar.getLabel() );
                barLabel.setHorizontalAlignment(JLabel.CENTER);
                labelPanel.add( barLabel );
            }
        }
    
        private class Bar
        {
            private String label;
            private int value;
            private Color color;
    
            public Bar(String label, int value, Color color)
            {
                this.label = label;
                this.value = value;
                this.color = color;
            }
    
            public String getLabel()
            {
                return label;
            }
    
            public int getValue()
            {
                return value;
            }
    
            public Color getColor()
            {
                return color;
            }
        }
    
        private class ColorIcon implements Icon
        {
            private int shadow = 3;
    
            private Color color;
            private int width;
            private int height;
    
            public ColorIcon(Color color, int width, int height)
            {
                this.color = color;
                this.width = width;
                this.height = height;
            }
    
            public int getIconWidth()
            {
                return width;
            }
    
            public int getIconHeight()
            {
                return height;
            }
    
            public void paintIcon(Component c, Graphics g, int x, int y)
            {
                g.setColor(color);
                g.fillRect(x, y, width - shadow, height);
                g.setColor(Color.GRAY);
                g.fillRect(x + width - shadow, y + shadow, shadow, height - shadow);
            }
        }
    
        private static void createAndShowGUI()
        {
            HistogramPanel panel = new HistogramPanel();
            panel.addHistogramColumn("A", 350, Color.RED);
            panel.addHistogramColumn("B", 690, Color.YELLOW);
            panel.addHistogramColumn("C", 510, Color.BLUE);
            panel.addHistogramColumn("D", 570, Color.ORANGE);
            panel.addHistogramColumn("E", 180, Color.MAGENTA);
            panel.addHistogramColumn("F", 504, Color.CYAN);
            panel.layoutHistogram();
    
            JFrame frame = new JFrame("Histogram Panel");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add( panel );
            frame.setLocationByPlatform( true );
            frame.pack();
            frame.setVisible( true );
        }
    
        public static void main(String[] args)
        {
            EventQueue.invokeLater(new Runnable()
            {
                public void run()
                {
                    createAndShowGUI();
                }
            });
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search