更改JFreeChart直方图颜色动态? [英] Change JFreeChart Histogram colors dynamically?

查看:647
本文介绍了更改JFreeChart直方图颜色动态?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试显示图片的直方图,只显示一些颜色。我已经做到了与JFreeChart和createXYLineChart,并通过遍历所有像素获取所有的数据。



为了加快速度,我尝试使用createHistogram。我已遵循



解决方案

根据您的片段和此

  import java.awt.BorderLayout; 
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Paint;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.DefaultDrawingSupplier;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StandardXYBarPainter;
import org.jfree.chart.renderer.xy.XYBarRenderer;
import org.jfree.data.statistics.HistogramDataset;

/ **
* @see http://stackoverflow.com/q/40537278/230513
* @see http://stackoverflow.com/q/11870416/ 230513
* @see http://stackoverflow.com/a/28519356/230513
* /
public class直方图{

private static final int BINS = 256 ;
private final BufferedImage image = getImage();
private HistogramDataset dataset;
private XYBarRenderer renderer;

private BufferedImage getImage(){
try {
return ImageIO.read(new URL(
http://i.imgur.com/kxXhIH1.jpg ));
} catch(IOException e){
e.printStackTrace(System.err);
}
return null;
}

private ChartPanel createChartPanel(){
// dataset
dataset = new HistogramDataset();
Raster raster = image.getRaster();
final int w = image.getWidth();
final int h = image.getHeight();
double [] r = new double [w * h];
r = raster.getSamples(0,0,w,h,0,r);
dataset.addSeries(Red,r,BINS);
r = raster.getSamples(0,0,w,h,1,r);
dataset.addSeries(Green,r,BINS);
r = raster.getSamples(0,0,w,h,2,r);
dataset.addSeries(Blue,r,BINS);
// chart
JFreeChart chart = ChartFactory.createHistogram(Histogram,Value,
Count,dataset,PlotOrientation.VERTICAL,true,true,false);
XYPlot plot =(XYPlot)chart.getPlot();
renderer =(XYBarRenderer)plot.getRenderer();
renderer.setBarPainter(new StandardXYBarPainter());
//透明的红色,绿色& blue
Paint [] paintArray = {
new Color(0x80ff0000,true),
new Color(0x8000ff00,true),
new Color(0x800000ff,true)
};
plot.setDrawingSupplier(new DefaultDrawingSupplier(
paintArray,
DefaultDrawingSupplier.DEFAULT_FILL_PAINT_SEQUENCE,
DefaultDrawingSupplier.DEFAULT_OUTLINE_PAINT_SEQUENCE,
DefaultDrawingSupplier.DEFAULT_STROKE_SEQUENCE,
DefaultDrawingSupplier.DEFAULT_OUTLINE_STROKE_SEQUENCE,
DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE));
ChartPanel panel = new ChartPanel(chart);
panel.setMouseWheelEnabled(true);
return panel;
}

private JPanel createControlPanel(){
JPanel panel = new JPanel();
panel.add(new JCheckbox(new VisibleAction(0)));
panel.add(new JCheckBox(new VisibleAction(1)));
panel.add(new JCheckBox(new VisibleAction(2)));
return panel;
}

private class VisibleAction extends AbstractAction {

private final int i;

public VisibleAction(int i){
this.i = i;
this.putValue(NAME,(String)dataset.getSeriesKey(i));
this.putValue(SELECTED_KEY,true);
renderer.setSeriesVisible(i,true);
}

@Override
public void actionPerformed(ActionEvent e){
renderer.setSeriesVisible(i,!renderer.getSeriesVisible(i));
}
}

private void display(){
JFrame f = new JFrame(Histogram);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(createChartPanel());
f.add(createControlPanel(),BorderLayout.SOUTH);
f.add(new JLabel(new ImageIcon(image)),BorderLayout.WEST);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}

public static void main(String [] args){
EventQueue.invokeLater(() - > {
new Histogram ;
});
}
}


I'm trying to show the histogram of an image and show only some colors. I've already done that with JFreeChart and createXYLineChart and getting all the data by iterating over all pixels.

To speed it up I'm trying to do it with "createHistogram". I've followed this code.

To update the chart with the new values I've used this two methods:

XYPlot plot = (XYPlot) chart.getPlot();
plot.setDataset(setHistogram(red, green, blue));

Being setHistogram a method which returns a HistogramDataset depending on which checkbox are activated (boolean red, green and blue).

That works properly as intended.

The second thing I must do when I do that is update the colors of each series, as otherwise they get the default value. I did it following more or less the same procedure as with the values:

private void setHistogramColors(boolean red, boolean green, boolean blue) {
    XYPlot plot = (XYPlot) chart.getPlot();
    XYBarRenderer renderer = (XYBarRenderer) plot.getRenderer();
    renderer.setBarPainter(new StandardXYBarPainter());
    Paint[] paintArray = null;
    if (red) {
        if (green) {
            if (blue) {
                paintArray = new Paint[3];
                paintArray[0] = new Color(0x80ff0000, true);// translucent red, green & blue
                paintArray[1] = new Color(0x8000ff00, true);
                paintArray[2] = new Color(0x800000ff, true);
            } else {
                paintArray = new Paint[2];
                paintArray[0] = new Color(0x80ff0000, true);
                paintArray[1] = new Color(0x8000ff00, true);
            }
        } else {
            paintArray = new Paint[1];
            paintArray[0] = new Color(0x80ff0000, true);
        }
    } else if (green) {
        if (blue) {
            paintArray = new Paint[2];
            paintArray[0] = new Color(0x8000ff00, true);
            paintArray[1] = new Color(0x800000ff, true);
        } else {
            paintArray = new Paint[1];
            paintArray[0] = new Color(0x8000ff00, true);
        }
    } else if (blue){
        paintArray = new Paint[1];
        paintArray[0] = new Color(0x800000ff, true);
    }
    else {
        return;
    }
    plot.setDrawingSupplier(new DefaultDrawingSupplier(
            paintArray,
            DefaultDrawingSupplier.DEFAULT_FILL_PAINT_SEQUENCE,
            DefaultDrawingSupplier.DEFAULT_OUTLINE_PAINT_SEQUENCE,
            DefaultDrawingSupplier.DEFAULT_STROKE_SEQUENCE,
            DefaultDrawingSupplier.DEFAULT_OUTLINE_STROKE_SEQUENCE,
            DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE));
}

But for what I can see this only works when I plot the code for the very first time, and the next plots of different series will take the sames colors. Here is an example, RGB are the color they are supposed to be: [ When I update with the red color goes to the green histogram and green's to the blue one:

Is there anyway to fix this?

解决方案

Based on your fragment and this comment, it looks like you are trying to change the display by adding and removing series from the dataset in your checkbox handlers. Instead of altering the model, change the visibility of a series in the view. In this case you can give each checkbox a suitable Action, as shown here and below. Note in particular that VisibleAction uses the series index that matches the corresponding color in the custom DrawingSupplier.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Paint;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.DefaultDrawingSupplier;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.StandardXYBarPainter;
import org.jfree.chart.renderer.xy.XYBarRenderer;
import org.jfree.data.statistics.HistogramDataset;

/**
 * @see http://stackoverflow.com/q/40537278/230513
 * @see http://stackoverflow.com/q/11870416/230513
 * @see http://stackoverflow.com/a/28519356/230513
 */
public class Histogram {

    private static final int BINS = 256;
    private final BufferedImage image = getImage();
    private HistogramDataset dataset;
    private XYBarRenderer renderer;

    private BufferedImage getImage() {
        try {
            return ImageIO.read(new URL(
                "http://i.imgur.com/kxXhIH1.jpg"));
        } catch (IOException e) {
            e.printStackTrace(System.err);
        }
        return null;
    }

    private ChartPanel createChartPanel() {
        // dataset
        dataset = new HistogramDataset();
        Raster raster = image.getRaster();
        final int w = image.getWidth();
        final int h = image.getHeight();
        double[] r = new double[w * h];
        r = raster.getSamples(0, 0, w, h, 0, r);
        dataset.addSeries("Red", r, BINS);
        r = raster.getSamples(0, 0, w, h, 1, r);
        dataset.addSeries("Green", r, BINS);
        r = raster.getSamples(0, 0, w, h, 2, r);
        dataset.addSeries("Blue", r, BINS);
        // chart
        JFreeChart chart = ChartFactory.createHistogram("Histogram", "Value",
            "Count", dataset, PlotOrientation.VERTICAL, true, true, false);
        XYPlot plot = (XYPlot) chart.getPlot();
        renderer = (XYBarRenderer) plot.getRenderer();
        renderer.setBarPainter(new StandardXYBarPainter());
        // translucent red, green & blue
        Paint[] paintArray = {
            new Color(0x80ff0000, true),
            new Color(0x8000ff00, true),
            new Color(0x800000ff, true)
        };
        plot.setDrawingSupplier(new DefaultDrawingSupplier(
            paintArray,
            DefaultDrawingSupplier.DEFAULT_FILL_PAINT_SEQUENCE,
            DefaultDrawingSupplier.DEFAULT_OUTLINE_PAINT_SEQUENCE,
            DefaultDrawingSupplier.DEFAULT_STROKE_SEQUENCE,
            DefaultDrawingSupplier.DEFAULT_OUTLINE_STROKE_SEQUENCE,
            DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE));
        ChartPanel panel = new ChartPanel(chart);
        panel.setMouseWheelEnabled(true);
        return panel;
    }

    private JPanel createControlPanel() {
        JPanel panel = new JPanel();
        panel.add(new JCheckBox(new VisibleAction(0)));
        panel.add(new JCheckBox(new VisibleAction(1)));
        panel.add(new JCheckBox(new VisibleAction(2)));
        return panel;
    }

    private class VisibleAction extends AbstractAction {

        private final int i;

        public VisibleAction(int i) {
            this.i = i;
            this.putValue(NAME, (String) dataset.getSeriesKey(i));
            this.putValue(SELECTED_KEY, true);
            renderer.setSeriesVisible(i, true);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            renderer.setSeriesVisible(i, !renderer.getSeriesVisible(i));
        }
    }

    private void display() {
        JFrame f = new JFrame("Histogram");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(createChartPanel());
        f.add(createControlPanel(), BorderLayout.SOUTH);
        f.add(new JLabel(new ImageIcon(image)), BorderLayout.WEST);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            new Histogram().display();
        });
    }
}

这篇关于更改JFreeChart直方图颜色动态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆