XY 块渲染器 jfreechart 中的块轮廓

Outline to blocks in XY Block renderer jfreechart

我正在使用 XYZ 数据集和 XY 块渲染器绘制一种热图。块的颜色是 Z 值的函数,颜色使用灰度分配。即,Z 值为 0 的块被分配为白色,Z 值最大的块被分配为黑色。 我的灰度从 0 到 100(或者更多)。如果尺度这么大,count 为 0 和 10 的块在颜色值上的差异很小。为了理解,可以说整个网格被分成块。一个方块的Z值为100,一个方块为2,其他方块均为0。那么,这个Z值为2的方块因为阴影很浅所以不太明显。

我想给一些颜色的方块画轮廓,这样它们就可以区分了。我尝试使用 setBaseItemOutline() 等函数,但 none 会这样做。

对此有任何帮助吗?

编辑:下方

我的 class 之一是这样的:

public class BlockRenderer extends ApplicationFrame {

/**
 * Constructs the demo application.
 *
 * @param title  the frame title.
 */
public BlockRenderer(String title) {
    super(title);
    JPanel chartPanel = createDemoPanel();
    //chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
    setContentPane(chartPanel);
}

/**
 * Creates a chart for the specified dataset.
 * 
 * @param dataset  the dataset.
 * 
 * @return A chart instance.
 */
private static JFreeChart createChart(XYZDataset dataset) {
    NumberAxis xAxis = new NumberAxis("X");
    xAxis.setLowerMargin(0.0);
    xAxis.setUpperMargin(0.0);
    NumberAxis yAxis = new NumberAxis("Y");
    yAxis.setAutoRangeIncludesZero(false);
    yAxis.setInverted(true);
    yAxis.setLowerMargin(0.0);
    yAxis.setUpperMargin(0.0);
    yAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
    XYBlockRenderer renderer = new XYBlockRenderer();
    CustomGrayPaintScale paintScale = new CustomGrayPaintScale(0,1000);   
    renderer.setPaintScale(paintScale);
    XYPlot plot = new XYPlot(dataset, xAxis, yAxis, renderer);
    plot.setBackgroundPaint(Color.lightGray);
    plot.setAxisOffset(new RectangleInsets(5, 5, 5, 5));
    JFreeChart chart = new JFreeChart("XYBlockChartDemo3", plot);
    chart.removeLegend();
    chart.setBackgroundPaint(Color.white);
    SymbolAxis scaleAxis = new SymbolAxis(null, new String[] {"", "OK", 
            "Uncertain", "Bad"});
    scaleAxis.setRange(0.5, 3.5);
    scaleAxis.setPlot(new PiePlot());
    scaleAxis.setGridBandsVisible(false);
    PaintScaleLegend psl = new PaintScaleLegend(paintScale, scaleAxis);
    psl.setAxisOffset(5.0);
    psl.setPosition(RectangleEdge.BOTTOM);
    psl.setMargin(new RectangleInsets(5, 5, 5, 5));
    chart.addSubtitle(psl);

    renderer.setBaseToolTipGenerator(new XYToolTipGenerator() {

        @Override
        public String generateToolTip(XYDataset dataset, int arg1, int arg2) {
            // TODO Auto-generated method stub
            XYZDataset xyzDataset = (XYZDataset)dataset; 
            return String.valueOf(xyzDataset.getZValue(arg1, arg2));
        }

    });

    return chart;
}

/**
 * Utility method called by createDataset().
 * 
 * @param data  the data array.
 * @param c  the column.
 * @param r  the row.
 * @param value  the value.
 */
private static void setValue(double[][] data, 
                             int c, int r, double value) {

    data[0][(r) * 10 + c] = c;
    data[1][(r) * 10 + c] = r;
    data[2][(r) * 10 + c] = value;

}

/**
 * Creates a sample dataset.
 */
private static XYZDataset createDataset() {

    double[] xvalues = new double[10*10];
    double[] yvalues = new double[10*10];        
    double[] zvalues = new double[10*10];
    double[][] data = new double[][] {xvalues, yvalues, zvalues};

    // set the default z-value to zero throughout the data array.
    int count [][] = new int[10][10];
    for ( int i=0; i<10; i++ ) {
        for ( int j=0; j<10; j++ ) {
            count[i][j] = i*j;
            if (  i==0 && j== 5 )
                count[i][j] = 3;
        }
    }

    for ( int i=0; i<10; i++ ) {
        for ( int j=0; j<10; j++ ) {
            setValue(data,j,i,count[i][j]);
        }
    }

    DefaultXYZDataset dataset = new DefaultXYZDataset();
    dataset.addSeries("Series 1", data);
    System.out.println(dataset.getZValue(0, 1));
    return dataset;
}

/**
 * Creates a panel for the demo.
 *  
 * @return A panel.
 */
public static JPanel createDemoPanel() {
    return new ChartPanel(createChart(createDataset()));
}

/**
 * Starting point for the demonstration application.
 *
 * @param args  ignored.
 */
public static void main(String[] args) {
    BlockRenderer demo = new BlockRenderer("Block Chart Demo 3");
    //demo.pack();
    demo.setExtendedState(java.awt.Frame.MAXIMIZED_BOTH);
    RefineryUtilities.centerFrameOnScreen(demo);
    demo.setVisible(true);
}

}

我已经让 CustomGrayPaintScale class 通过覆盖其 getPaint() 获得 0 Z 值的白色。如果上面的 class 是 运行,我们会注意到块没有太大区别。顶行有一个值为 3 的单元格,该行中的所有其他单元格均为 0。由于我的范围很大,它的颜色值与相邻的颜色值相差不大。所以,我想要一些可以为这些块画出轮廓的东西。另外,我想给一些方块物品分配蓝色,而其他方块物品应该只根据 Z 值设置油漆比例(如果设计油漆比例会更好,它会为所有物品分配不同强度级别的任何颜色(绿色除外),而不是给方块赋予所有不同颜色的光谱油漆比例)。 我怎样才能做到这一点?

XYBlockRenderer ignores the outline properties inherited from the parent, AbstractRenderer. The drawItem() method simply sets the paint returned from the PaintScalefill()draw()使用相同的颜色。一些可能的方法包括:

  • 覆盖 drawItem() 并在 fill() 之后但在 draw() 之前设置不同的颜色,也许使用 brighter()darker() 颜色.

  • 使用 GrayPaintScale 以外的 PaintScale,例如 LookupPaintScale 或您自己的实现。您可以在问题结束时指定更独特的颜色,也许使用 Color.getHSBColor() 来改变色调、饱和度 and/or 亮度。

    • 这个 example 实现了 PaintScale 接口。

    • exampleXYLineAndShapeRenderer 的方式改变色调。

    • exampleGanttRenderer 的方式改变饱和度。