java JFreeChart - 将图表线的 SeriesStroke 从实线改为虚线

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13240410/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 11:59:38  来源:igfitidea点击:

JFreeChart - change SeriesStroke of chart lines from solid to dashed in one line

javachartsjfreecharttime-seriestimeserieschart

提问by MAK Design Labs

The answer accepted here (JFreechart(Java) - How to draw lines that is partially dashed lines and partially solid lines?) helped me start down the path of changing my seriesstroke lines on my chart. After stepping through my code and watching the changes, I see that my seriesstroke does in fact change to "dashedStroke" when it is supposed to (after a certain date "dashedAfter"), but when the chart is rendered the entire series line is dashed. How can I get a series line to be drawn solid at first and dashed after a set date?

此处接受的答案(JFreechart(Java) - 如何绘制部分为虚线和部分实线的线条?)帮助我开始更改图表上的系列笔划线。在单步执行我的代码并观察更改后,我发现我的系列笔划实际上在它应该更改为“dashedStroke”时(在某个日期“dashedAfter”之后),但是当图表呈现时,整个系列线是虚线. 如何在设定日期后首先绘制实线并绘制虚线?

/* series line modifications */
final Number dashedAfter = timeNowDate.getTime();

XYLineAndShapeRenderer render = new XYLineAndShapeRenderer() {
  Stroke regularStroke = new BasicStroke();
  Stroke dashedStroke = new BasicStroke(
                            1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND,
                            1.0f, new float[] {10.0f, 6.0f}, 0.0f );
  @Override
  public Stroke getItemStroke(int row, int column) {
    Number xVal = cd.getXValue(row, column);
    if (xVal.doubleValue() > dashedAfter.doubleValue()) { 
      return dashedStroke; 
    } else { 
      return regularStroke; 
    }
  }
};
render.setBaseShapesVisible(false);
render.setBaseShapesFilled(true);
render.setDrawSeriesLineAsPath(true);
plot.setRenderer(render);

采纳答案by GrahamA

Have you tried implementing AbstractRenderer#getItemStroke?

你试过实施AbstractRenderer#getItemStroke吗?

enter image description here

在此处输入图片说明

In this example I'm using a dashed line for x > 4 for series 2:

在这个例子中,我对系列​​ 2 使用 x > 4 的虚线:

XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer(){
    Stroke soild = new BasicStroke(2.0f);
    Stroke dashed =  new BasicStroke(1.0f,BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, new float[] {10.0f}, 0.0f);
    @Override
    public Stroke getItemStroke(int row, int column) {
if (row == 2){
  double x = dataset.getXValue(row, column);
  if ( x > 4){
    return dashed;
  } else {
    return soild;
  } 
} else
  return super.getItemStroke(row, column);
    }
  };
  renderer.setBaseShapesVisible(true);
  renderer.setBaseShapesFilled(true);
  renderer.setBaseStroke(new BasicStroke(3));
  plot.setRenderer(renderer);

Although this example is using and XYSeriesand not dates you shold be able to modify it for you needs.

尽管此示例使用和XYSeries而不是日期,但您可以根据需要对其进行修改。

Here is the full example

这是完整的例子

import java.awt.BasicStroke;
import java.awt.Stroke;

import javax.swing.JPanel;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.ApplicationFrame;
import org.jfree.ui.RefineryUtilities;

public class LineChartDemo2 extends ApplicationFrame {

    public LineChartDemo2(String title) {
        super(title);
        JPanel chartPanel = createDemoPanel();
        chartPanel.setPreferredSize(new java.awt.Dimension(500, 270));
        setContentPane(chartPanel);
    }

    private static JFreeChart createChart(final XYDataset dataset) {

        JFreeChart chart = ChartFactory.createXYLineChart(
            "Line Chart Demo: XYLineAndShapeRenderer",     
            "X",                     
            "Y",                     
            dataset,              
            PlotOrientation.VERTICAL,
            false,                     
            false,                 
            false             
        );

        XYPlot plot = (XYPlot) chart.getPlot();
        plot.setDomainPannable(true);
        plot.setRangePannable(true);

        XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer(){
            Stroke soild = new BasicStroke(2.0f);
            Stroke dashed =  new BasicStroke(1.0f,BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10.0f, new float[] {10.0f}, 0.0f);
            @Override
            public Stroke getItemStroke(int row, int column) {
                if (row == 2){
                    double x = dataset.getXValue(row, column);
                    if ( x > 4){
                        return dashed;
                    } else {
                        return soild;
                    } 
                } else
                    return super.getItemStroke(row, column);
            }
        };

        renderer.setBaseShapesVisible(true);
        renderer.setBaseShapesFilled(true);
        renderer.setBaseStroke(new BasicStroke(3));
        plot.setRenderer(renderer);
        return chart;
    }

    public static JPanel createDemoPanel() {
        JFreeChart chart = createChart(createDataset());
        ChartPanel panel = new ChartPanel(chart);
        panel.setMouseWheelEnabled(true);
        return panel;
    }

    public static void main(String[] args) {
        LineChartDemo2 demo = new LineChartDemo2(
                "JFreeChart");
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);
    }

    private static XYDataset createDataset() {

        XYSeries series1 = new XYSeries("First");
        series1.add(1.0, 1.0);
        series1.add(2.0, 4.0);
        series1.add(3.0, 3.0);
        series1.add(4.0, 5.0);
        series1.add(5.0, 5.0);
        series1.add(6.0, 7.0);
        series1.add(7.0, 7.0);
        series1.add(8.0, 8.0);

        XYSeries series2 = new XYSeries("Second");
        series2.add(1.0, 5.0);
        series2.add(2.0, 7.0);
        series2.add(3.0, 6.0);
        series2.add(4.0, 8.0);
        series2.add(5.0, 4.0);
        series2.add(6.0, 4.0);
        series2.add(7.0, 2.0);
        series2.add(8.0, 1.0);

        XYSeries series3 = new XYSeries("Third");
        series3.add(3.0, 4.0);
        series3.add(4.0, 3.0);
        series3.add(5.0, 2.0);
        series3.add(6.0, 3.0);
        series3.add(7.0, 6.0);
        series3.add(8.0, 3.0);
        series3.add(9.0, 4.0);
        series3.add(10.0, 3.0);

        XYSeriesCollection dataset = new XYSeriesCollection();
        dataset.addSeries(series1);
        dataset.addSeries(series2);
        dataset.addSeries(series3);

        return dataset;

    }


}

回答by trashgod

I'm still having the same problem of the line not changing from solid to dashed, but being one or the other.

我仍然遇到相同的问题,即线条没有从实线变为虚线,而是其中之一。

The setDrawSeriesLineAsPath()method "controls whether or not each series is drawn as a single path." This precludes changing the Strokedynamically, as getItemStroke()will be called only once per series.

setDrawSeriesLineAsPath()方法“控制是否将每个系列绘制为单个路径。” 这排除了Stroke动态更改,因为getItemStroke()每个系列只会调用一次。

Addendum: An easy way to verify this is to invoke setDrawSeriesLineAsPath()in @GrahamA's example and break in drawFirstPassShape()in the debugger.

附录:验证这一点的一种简单方法是setDrawSeriesLineAsPath()在@GrahamA 的示例中调用并drawFirstPassShape()进入调试器。

回答by fonZ

I think that you do it right and if it doesnt work maybe its not possible? Im just guessing here but you could draw 2 lines instead of 1. Your second line would begin where your first line ends. That could get messy if you want to change the stroke alot and as you want to change it every iteration of your loop depending on a condition, your code will probably get alot more complicated. Or just draw a new line for each.

我认为你做得对,如果它不起作用,也许它不可能?我只是在这里猜测,但您可以绘制 2 条线而不是 1 条。您的第二条线将从第一条线结束的地方开始。如果您想大量更改笔划并且您想根据条件在循环的每次迭代中更改它,那可能会变得混乱,您的代码可能会变得更加复杂。或者只是为每个画一条新线。