JFreeChart选择区域而不缩放

7
我最近开始使用JFreeChart,有些事情我想做但不确定是否可行。我的程序需要从一个wav文件中绘制频谱图(声音图形)。所以我成功地将wav文件的数据存储在一个双重数组列表中,并在图表中显示出来。但现在我想选择我的频谱图中的一个区域(使用缩放工具)而不进行缩放,并且仅播放所选部分的声音。但是我无法找到任何方法来实现这一点。下面是我的图表代码:
    package classes;

import java.awt.Color;
import java.awt.Paint;
import java.awt.Rectangle;
import java.io.File;
import java.io.IOException;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.RectangleInsets;

public class Chart{
    JFreeChart chart;
    Plot plot;

    //Constructeur de la classe Chart
    public Chart(double[][] bs, int channel, int framesLength, float frameRate)
    {
        // Création d'un XY chart
        XYSeries series = new XYSeries("XYGraph");
        int i=0,j=0;
        float k=0;
        //Ajout de tous les points du tableau de 16 bytes dans le chart
        for( i=0; i <channel;i++)
        {
            for(j=0; j< framesLength;j++)
            {
                //Division des valeurs par 2^15 pour être entre 1 et -1
                series.add(k, (bs[i][j]/32768));
                //Echelle de X
                k+=(1/frameRate);
            }
        }
        // Ajoute la série au dataset
        XYSeriesCollection dataset = new XYSeriesCollection();
        dataset.addSeries(series);
        // Génération du graphe
        chart = ChartFactory.createXYLineChart(
        "Ajouter titre à la fonction de génération", // Titre
        "Temps (s)", // Nom de l'axe X
        "y-axis", // Nom de l'axe Y
        dataset, // Dataset
        PlotOrientation.VERTICAL, // Plot Orientation
        true, // Show Legend
        false, // Use tooltips
        false // Configure chart to generate URLs?
        );
        plot= (XYPlot) chart.getPlot();

    }
    //Renvoie le chart
    public JFreeChart getChart()
    {
        return chart;
    }

    public void color(Color c)
    {
        plot.setBackgroundPaint(c);
    }
}

这里我调用了Chart类并使用它:

Chart chartUn= new Chart(bs, channels  , frameLength , frameRate);
        chartUn.color(Color.pink);
        vue.setChartPanelUn(new ChartPanel(chartUn.getChart(), false));
        vue.getChartPanelUn().setRangeZoomable(false);
        vue.getChartPanelUn().setMouseWheelEnabled(true);

vue.getChartPanelUn() 返回一个 ChartPanel。

你有没有想法如何解决我的问题?

谢谢 (如果我的英语不太准确,请原谅 :/)

1个回答

14
不要通过缩放来实现此操作,而是使用添加到ChartPanelMouseListenerMarker添加到Domain轴上。在这个例子中,我已经对MouseAdapter进行了子类化,以便在按下鼠标时捕获域值(markerStart),并在释放鼠标的位置更新结束点('markerEnd'),然后将标记添加到图表中(updateMarker)。然后你会得到这样一个图表:

Chart with Domain Marker

请注意,在此示例中,我实际上已经关闭了缩放功能。
import java.awt.Color;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

import javax.swing.JFrame;
import javax.swing.JPanel;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.IntervalMarker;
import org.jfree.chart.plot.Marker;
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.Layer;


public class MouseMarkerDemo extends JFrame {


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


    private final static class  MouseMarker extends MouseAdapter{
        private Marker marker;
        private Double markerStart = Double.NaN;
        private Double markerEnd = Double.NaN;
        private final XYPlot plot;
        private final JFreeChart chart;
        private  final ChartPanel panel;


        public MouseMarker(ChartPanel panel) {
            this.panel = panel;
            this.chart = panel.getChart();
            this.plot = (XYPlot) chart.getPlot();
        }

        private void updateMarker(){
            if (marker != null){
                plot.removeDomainMarker(marker,Layer.BACKGROUND);
            }
            if (!( markerStart.isNaN() && markerEnd.isNaN())){
                if ( markerEnd > markerStart){
                    marker = new IntervalMarker(markerStart, markerEnd);
                    marker.setPaint(new Color(0xDD, 0xFF, 0xDD, 0x80));
                    marker.setAlpha(0.5f);
                    plot.addDomainMarker(marker,Layer.BACKGROUND);
                }
            }
        }

        private Double getPosition(MouseEvent e){
            Point2D p = panel.translateScreenToJava2D( e.getPoint());
            Rectangle2D plotArea = panel.getScreenDataArea();
            XYPlot plot = (XYPlot) chart.getPlot();
            return plot.getDomainAxis().java2DToValue(p.getX(), plotArea, plot.getDomainAxisEdge());
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            markerEnd = getPosition(e);
            updateMarker();
        }

        @Override
        public void mousePressed(MouseEvent e) {
            markerStart = getPosition(e);
        }
    }

    private static XYDataset createDataset() {

        XYSeries series1 = new XYSeries("Data");
        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);

        XYSeriesCollection dataset = new XYSeriesCollection();
        dataset.addSeries(series1);
        return dataset;

    }


    private static JFreeChart createChart(XYDataset dataset) {

        JFreeChart chart = ChartFactory.createXYLineChart(
            "Mouse Marker",
            "X",
            "Y",
            dataset,
            PlotOrientation.VERTICAL,
            true,
            true,
            false
        );
        XYPlot plot = (XYPlot) chart.getPlot();
        plot.setDomainPannable(true);
        plot.setRangePannable(true);
        XYLineAndShapeRenderer renderer
                = (XYLineAndShapeRenderer) plot.getRenderer();
        renderer.setBaseShapesVisible(true);
        renderer.setBaseShapesFilled(true);
        return chart;
    }

    public static JPanel createDemoPanel() {
        final JFreeChart chart = createChart(createDataset());
        final ChartPanel panel = new ChartPanel(chart);
        panel.setRangeZoomable(false);
        panel.setDomainZoomable(false);
        panel.addMouseListener(new MouseMarker(panel));
        return panel;
    }

    public static void main(String[] args) {
        MouseMarkerDemo demo = new MouseMarkerDemo("JFreeChart: MouseMarkerDemo.java");
        demo.pack();
        demo.setVisible(true);
    }

}

谢谢你的快速回答!我打算这个周末尝试一下,看看是否与我的代码兼容。 - user2299206
谢谢Graham,我从你的例子中借鉴了一些,第一次就成功了。 - Quinn Carver

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接