I recently started using JFreeChart and there is something i would like to do but i'm not sure if it's possible. My program is supposed to draw a spectrogram (a sound graph) from a wav file. So i managed to get the data from my wav file in a double arraylist and to display it in a chart. But now i would like to be able to select an area of my spectrogram (with the same tool used for zooming) without zooming and to be able to play only the selected part on my sound. But i simply can't find any way to succeed. Here is my code of my chart:
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);
}
}
And here i'm calling the Chart class and using it:
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() returns a ChartPanel. Would you have an idée how to solve my problem? Thanks a lot (And sorry if my english is not always exact :/)
Don't do this by zooming, use a MouseListener
added to your ChartPanel
to add a Marker
to the Domain
axis.
In this example I have subclassed MouseAdapter
so that when you press the mouse down the domain value is captured (markerStart
) and when you release the mouse end postition is updated ('markerEnd') and a Marker is added to the plot (updateMarker
)
You will then get a chart like this:
Note that in this example I've actually turned off the zooming.
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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With