如何在Java中绘制类似Matlab stem()的离散信号图?
在Java中实现仅含垂直线的离散信号图(类似Matlab stem())
Java完全可以实现你需求的仅保留垂直线的离散信号图,无需依赖JFreeChart的现成工具类,以下提供两种可行方案:
方案一:自定义Swing组件直接绘制
通过Swing的Graphics2D API手动绘制垂直线,这种方式轻量且完全可控,步骤如下:
- 创建继承
JPanel的自定义组件,重写paintComponent方法 - 将输入的x、y数组坐标映射到组件的像素坐标系
- 遍历每个数据点,绘制从x轴(y=0对应的像素位置)到数据点的垂直线
示例代码:
import javax.swing.*; import java.awt.*; import java.util.Arrays; public class StemPlotPanel extends JPanel { private double[] xData; private double[] yData; private static final int PADDING = 50; private static final int LINE_WIDTH = 2; public StemPlotPanel(double[] xData, double[] yData) { this.xData = xData; this.yData = yData; setPreferredSize(new Dimension(800, 600)); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g; g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setStroke(new BasicStroke(LINE_WIDTH)); // 计算坐标轴范围 double minX = Arrays.stream(xData).min().orElse(0); double maxX = Arrays.stream(xData).max().orElse(10); double minY = Arrays.stream(yData).min().orElse(-5); double maxY = Arrays.stream(yData).max().orElse(5); // 确保包含y=0的x轴 minY = Math.min(minY, 0); maxY = Math.max(maxY, 0); // 计算坐标映射比例 double xScale = (getWidth() - 2 * PADDING) / (maxX - minX); double yScale = (getHeight() - 2 * PADDING) / (maxY - minY); // 绘制x轴和y轴 int xAxisY = PADDING + (int) ((0 - minY) * yScale); int yAxisX = PADDING + (int) ((0 - minX) * xScale); g2d.drawLine(PADDING, xAxisY, getWidth() - PADDING, xAxisY); g2d.drawLine(yAxisX, PADDING, yAxisX, getHeight() - PADDING); // 绘制垂直线 g2d.setColor(Color.BLUE); for (int i = 0; i < xData.length; i++) { double x = xData[i]; double y = yData[i]; // 转换为像素坐标 int pixelX = PADDING + (int) ((x - minX) * xScale); int pixelY = PADDING + (int) ((maxY - y) * yScale); // 绘制从x轴到数据点的垂直线 g2d.drawLine(pixelX, xAxisY, pixelX, pixelY); } } public static void main(String[] args) { double[] x = {1, 2, 3, 4, 5, 6}; double[] y = {2, -1, 3, 0, -2, 1}; JFrame frame = new JFrame("离散信号垂直线图"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new StemPlotPanel(x, y)); frame.pack(); frame.setVisible(true); } }
方案二:基于JFreeChart扩展实现
如果你仍想使用JFreeChart,可以通过自定义数据集和渲染器来实现仅显示垂直线的效果:
- 构造
XYSeries时,为每个数据点添加两个坐标:(x, 0)和(x, y) - 使用
XYLineAndShapeRenderer,关闭数据点形状的显示,只保留线段绘制
示例代码:
import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.XYSeriesCollection; import javax.swing.*; public class JFreeChartStemPlot { public static void main(String[] args) { double[] x = {1, 2, 3, 4, 5, 6}; double[] y = {2, -1, 3, 0, -2, 1}; // 构造数据集:每个数据点对应(x,0)和(x,y)两个点 XYSeries series = new XYSeries("离散信号"); for (int i = 0; i < x.length; i++) { series.add(x[i], 0); series.add(x[i], y[i]); } XYSeriesCollection dataset = new XYSeriesCollection(series); // 创建图表并配置渲染器 JFreeChart chart = ChartFactory.createXYLineChart( "离散信号垂直线图", "X轴", "Y轴", dataset ); XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) chart.getXYPlot().getRenderer(); // 关闭数据点形状显示 renderer.setSeriesShapesVisible(0, false); // 设置线段宽度 renderer.setSeriesStroke(0, new java.awt.BasicStroke(2)); // 显示图表 JFrame frame = new JFrame("JFreeChart离散信号图"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new ChartPanel(chart)); frame.pack(); frame.setVisible(true); } }
两种方案都能实现仅保留垂直线的离散信号图,你可以根据项目依赖(是否使用JFreeChart)选择合适的方式。
内容的提问来源于stack exchange,提问作者MrManini
相关产品推荐
相关产品推荐

