【问题标题】:Outline to blocks in XY Block renderer jfreechartXY块渲染器jfreechart中的块轮廓
【发布时间】:2020-08-26 06:36:13
【问题描述】:

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

我想为某些颜色的块提供轮廓,以便它们可以区分。我尝试了 setBaseItemOutline() 等函数,但没有一个。

有什么帮助吗?

编辑:下方

我的一门课是这样的:

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 类,通过覆盖其 getPaint() 来获得 0 Z 值的白色。如果运行上面的类,我们会注意到这些块没有太大区别。顶行有一个值为 3 的单元格,该行中的所有其他单元格都是 0。由于我的范围很大,它的颜色值与其相邻的值相差不大。所以,我想要一些可以为这些块绘制轮廓的东西。另外,我想将蓝色分配给某些块项目,而其他项目应该仅基于 Z 值具有油漆刻度(如果油漆刻度设计为将任何颜色的不同强度级别(例如绿色)分配给所有项目,而不是光谱油漆比例,它为块提供所有不同的颜色)。 我怎样才能做到这一点?

【问题讨论】:

    标签: java jfreechart heatmap binning


    【解决方案1】:

    XYBlockRenderer 忽略从父级AbstractRenderer 继承的大纲属性。 drawItem() 方法简单地设置从PaintScale 返回的绘制,对both fill() draw() 使用相同的颜色。一些可能的方法包括:

    • 覆盖drawItem() 并在fill() 之后但draw() 之前设置不同的绘画,可能使用brighter()darker() 颜色。

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

      • 这个example 实现了PaintScale 接口。

      • 这个example 改变了XYLineAndShapeRenderer 中的色调。

      • 这个example 改变了GanttRenderer 中的饱和度。

    【讨论】:

    • 可以给像浅蓝色这样的背景颜色吗?我认为这些项目将是可区分的,但 XYBlockRenderer 是否允许设置背景?似乎不像我试过的那样。
    • 对。默认情况下,XYBlockRenderer 使用与fill() 块和draw() 轮廓相同的颜色。您必须决定是覆盖 drawItem() 还是使用不同的 PaintScale
    • 有什么方法可以让一个块在点击时改变它的颜色或突出显示?
    • 对于example,但这是一个不同的问题。
    • drawItem() 方法调用getPaint(),而不是getItemPaint()。如需进一步指导,请编辑您的问题以包含minimal reproducible example
    猜你喜欢
    • 1970-01-01
    • 2011-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多