2012-03-23 15 views
6

Ho chart.png con i dati al suo interno che vorrei inserire un semplice asse X - Y con alcune etichette. Mi piacerebbe anche provare a non utilizzare alcun software esterno che non sia fornito con java. Mi è permesso usare jfreechart ma se c'è un modo per renderlo bello, mentre si usa un po 'di codice Java, sarebbe meglio. Qualcuno ha una buona idea su come fare questo genere di cose?Come posso inserire assi su un file .png in java?

Aggiornamento: Qualcosa di simile, ma i dati sarebbero codificati a colori con valori rgb e ovviamente non ci sarebbe alcun asse/etichettatura.

pyplot latency example http://www.goldb.org/goldblog/cmg_images/pylot_latency_sample.png

Questo grafico è solo un esempio sembra niente come quello che i miei grafici attuali sembrano ... Il mio vero grafici possono avere ogni valore di colore RGB in loro. Io so come creare la trama, solo che non so come mettere all'asse/etichettatura sul BufferImage che ho creato

+0

Puoi collegarti al 'png'? Hai i dati originali? – trashgod

+0

Qualcosa come questo http://www.goldb.org/goldblog/cmg_images/pylot_latency_sample.png ma sarebbe solo il blu e il bianco in un png – Grammin

+0

Vuoi veramente modificare l'immagine esistente? I dati esistenti sono importanti? Perché non creare un nuovo grafico che assomigli all'immagine? – trashgod

risposta

14

Non penso che la modifica di un'immagine statica funzionerà molto bene, poiché porterà inevitabilmente a errori di registrazione e stili non corrispondenti. Invece, integra qualsiasi rendering nella creazione del grafico. Utilizzando l'approccio delineato here, il numero sscce di seguito illustra alcuni modi per personalizzare le forme, i colori e gli assi visualizzati come desiderato.

Addendum: per colorare i singoli elementi, l'API raccomanda l'approccio mostrato here, in cui un renderizzatore personalizzato sovrascrive getItemPaint(). Color.getHSBColor() viene utilizzato per creare uno spettro completo di colori.

Response Time chart

Ecco l'originale, renderer di default per il confronto:

Response Time chart

import java.awt.Color; 
import java.awt.EventQueue; 
import java.awt.Paint; 
import java.awt.Shape; 
import java.awt.geom.Ellipse2D; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.Random; 
import javax.swing.JFrame; 
import org.jfree.chart.ChartFactory; 
import org.jfree.chart.ChartPanel; 
import org.jfree.chart.JFreeChart; 
import org.jfree.chart.axis.ValueAxis; 
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; 

/** @see https://stackoverflow.com/q/9843451/230513 */ 
public class ResponseTime { 

    private static final int N = 600; 
    private static final String title = "ResponseTime"; 
    private static final Random random = new Random(); 
    private static final Shape circle = new Ellipse2D.Double(-3, -3, 6, 6); 
    private static final Color line = Color.gray; 

    private ChartPanel createPanel() { 
     JFreeChart chart = ChartFactory.createXYLineChart(
      title, "Elapsed Time (secs)", "Response Time (secs)", 
      createDataset(), PlotOrientation.VERTICAL, true, true, false); 
     XYPlot plot = chart.getXYPlot(); 
     MyRenderer renderer = new MyRenderer(true, true, N); 
     plot.setRenderer(renderer); 
     renderer.setSeriesShape(0, circle); 
     renderer.setSeriesPaint(0, line); 
     renderer.setUseFillPaint(true); 
     renderer.setSeriesShapesFilled(0, true); 
     renderer.setSeriesShapesVisible(0, true); 
     renderer.setUseOutlinePaint(true); 
     renderer.setSeriesOutlinePaint(0, line); 
     ValueAxis range = plot.getRangeAxis(); 
     range.setLowerBound(0.5); 
     return new ChartPanel(chart); 
    } 

    private static class MyRenderer extends XYLineAndShapeRenderer { 

     private List<Color> clut; 

     public MyRenderer(boolean lines, boolean shapes, int n) { 
      super(lines, shapes); 
      clut = new ArrayList<Color>(n); 
      for (int i = 0; i < n; i++) { 
       clut.add(Color.getHSBColor((float) i/n, 1, 1)); 
      } 
     } 

     @Override 
     public Paint getItemFillPaint(int row, int column) { 
      return clut.get(column); 
     } 
    } 

    private XYDataset createDataset() { 
     XYSeriesCollection result = new XYSeriesCollection(); 
     XYSeries series = new XYSeries("Series 1"); 
     for (double x = 0; x < N - 1; x++) { 
      series.add(x, f(x)); 
     } 
     series.add(25, 1.75); // outlier 
     result.addSeries(series); 
     return result; 
    } 

    private double f(double x) { 
     double y = 0.004 * x + .75; 
     return y + random.nextGaussian() * y/10; 
    } 

    private void display() { 
     JFrame f = new JFrame(title); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.add(createPanel()); 
     f.pack(); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       new ResponseTime().display(); 
      } 
     }); 
    } 
} 
+0

Grazie per l'esempio di codice molto dettagliato! Come potrei fare qualcosa come: Random rg = new Random(); for (double x = 0; x <600; x ++) {Color randColor = new Color (rg.nextInt (255), rg.nextInt (255), rg.nextInt (255)); randomseries.add (x, f (x), randColor.getRGB());} – Grammin

+0

Immagino che il mio problema principale sia ottenere i colori corretti sul grafico? – Grammin

+0

ottima risposta, davvero – mKorbel

0

avevo letto l'immagine in un BufferedImage e quindi utilizzare i metodi drawXxxx() sull'immagine del Graphics istanza.

Quindi, si può scrivere di nuovo l'immagine in un file o visualizzarla in alcune gui.

+0

Ho l'Immagine in una BufferedImage, ma non so quanto sarà difficile per disegnare etichette e linee di gamma/dominio – Grammin

0

Per quanto posso capire, sarebbe molto difficile. Con la tua immagine pronta, puoi disegnare qualsiasi altra cosa su di essa, ma come calcoli l'unità per renderla proporzionale all'immagine? Come impaginare l'intera immagine in un secondo momento? Con uno strumento per grafici come jfreechart, sei molto libero di giocare con le etichette, gli assi e le unità. Ma quando si tratta di disegnarli dopo che il grafico è stato effettivamente creato, le cose saranno molto complicate. Non ho idea del motivo per cui vuoi disegnare assi o se vuoi mostrare quei grafici sul web. Ho trovato i grafici generati con jfreechart a volte non sembrano molto belli sulle pagine web - il testo sembra sfocato e il colore del carattere non corrisponde ad altro testo sulla stessa pagina.

Se state per inserirli in pagine Web, un'altra scelta sarebbe quella di utilizzare Javascript per recuperare i dati dal server e disegnare il grafico al volo sul lato client.

3

penso che la biblioteca JFreeChart è il modo giusto per implementa il rapporto.

Ma se stai cercando codice per disegnare qualche etichetta su un'immagine, eccola qui.

public static void main(String[] args) 
    throws IOException 
{ 
    JFrame frame = new JFrame(); 
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
    frame.setLocationRelativeTo(null); 
    frame.setSize(800, 600); 

    BufferedImage modifiedImg = ImageIO.read(new File("c:\\test.png")); 
    Graphics graphics = modifiedImg.getGraphics(); 
    graphics.setColor(Color.red); 
    graphics.drawString("Label", 100, 100);// draw text 
    graphics.drawLine(1, 100, 100, 100);// draw line 

    JLabel label = new JLabel(); 
    label.setIcon(new ImageIcon(modifiedImg)); 
    frame.getContentPane().add(label, BorderLayout.CENTER); 

    frame.setVisible(true); 
} 

Non utilizzo la jfreechart, stiamo usando Jide, ottengono una libreria di grafici carina. Mi piace, tranne il prezzo, ma il capo lo ha pagato comunque. Puoi vedere lo screenshot qui: http://www.jidesoft.com/products/charts.htm

Problemi correlati