2013-04-19 9 views
7

Recentemente ho iniziato a utilizzare JFreeChart e c'è qualcosa che mi piacerebbe fare ma non sono sicuro che sia possibile. Il mio programma dovrebbe disegnare uno spettrogramma (un grafico sonoro) da un file wav. Così sono riuscito a ottenere i dati dal mio file wav in un doppio arraylist e visualizzarlo in un grafico. Ma ora mi piacerebbe essere in grado di selezionare un'area del mio spettrogramma (con lo stesso strumento utilizzato per lo zoom) senza zoom e di essere in grado di riprodurre solo la parte selezionata sul mio suono. Ma semplicemente non riesco a trovare alcun modo per avere successo. Ecco il mio codice di mio grafico:JFreeChart seleziona un'area senza zoom

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); 
    } 
} 

E qui sto chiamando la classe Chart e usarlo:

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() restituisce un ChartPanel. Vuoi un'idea per risolvere il mio problema? Grazie mille (e scusate se il mio inglese non è sempre precisa: /)

risposta

12

Non fare questo con lo zoom, utilizzare un MouseListener aggiunto al tuo ChartPanel per aggiungere un Marker all'asse Domain.

In questo esempio ho sottoclasse MouseAdapter in modo che quando si preme il mouse verso il basso il valore di dominio viene catturato (markerStart) e quando si rilascia il postition fine del mouse viene aggiornato ('markerEnd') e di un marcatore viene aggiunto alla trama (updateMarker)

sarà quindi ottenere un grafico come questo:

Chart with Domain Marker

Si noti che in questo esempio realtà ho spento lo zoom.

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); 
    } 

} 
+0

Grazie per la rapida risposta! Ci proverò questo fine settimana per vedere se funziona con il mio codice – user2299206

Problemi correlati