动态更改 JFreeChart 直方图颜色?
Change JFreeChart Histogram colors dynamically?
我正在尝试显示图像的直方图并且只显示一些颜色。我已经使用 JFreeChart 和 createXYLineChart 并通过遍历所有像素来获取所有数据。
为了加快速度,我尝试使用 "createHistogram" 来完成。我关注了 .
为了用新值更新图表,我使用了这两种方法:
XYPlot plot = (XYPlot) chart.getPlot();
plot.setDataset(setHistogram(red, green, blue));
作为 setHistogram 方法,returns 一个 HistogramDataset 取决于激活的复选框(布尔值红色、绿色和蓝色)。
按预期正常工作。
我必须做的第二件事是更新每个系列的颜色,否则它们将获得默认值。我或多或少遵循与值相同的过程:
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));
}
但据我所知,这仅在我第一次绘制代码时有效,并且不同系列的下一个图将采用相同的颜色。这是一个例子,RGB 是它们应该是的颜色:
[
当我更新为红色时,绿色直方图变为绿色直方图,绿色变为蓝色直方图:
有办法解决这个问题吗?
基于你的片段和这个, 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
* @see
* @see
*/
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 和 createXYLineChart 并通过遍历所有像素来获取所有数据。
为了加快速度,我尝试使用 "createHistogram" 来完成。我关注了
为了用新值更新图表,我使用了这两种方法:
XYPlot plot = (XYPlot) chart.getPlot();
plot.setDataset(setHistogram(red, green, blue));
作为 setHistogram 方法,returns 一个 HistogramDataset 取决于激活的复选框(布尔值红色、绿色和蓝色)。
按预期正常工作。
我必须做的第二件事是更新每个系列的颜色,否则它们将获得默认值。我或多或少遵循与值相同的过程:
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));
}
但据我所知,这仅在我第一次绘制代码时有效,并且不同系列的下一个图将采用相同的颜色。这是一个例子,RGB 是它们应该是的颜色:
[
有办法解决这个问题吗?
基于你的片段和这个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
* @see
* @see
*/
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();
});
}
}