2012-03-23 7 views
6

Mam chart.png z danymi w nim, że chciałbym umieścić prostą oś X-Y na niektórych etykietach. Chciałbym również spróbować nie używać zewnętrznego oprogramowania, które nie jest dostarczane z java. Mogę używać jfreechart, ale jeśli jest jakiś sposób, aby wyglądał ładnie, a przy użyciu jakiegoś kodu Javy planu, byłoby lepiej. Czy ktoś ma dobre pojęcie o tym, jak robić takie rzeczy?Jak mogę umieścić oś na pliku .png w java?

Aktualizacja: Coś takiego, ale dane byłyby oznaczone kolorami z wartościami rgb i oczywiście nie byłoby osi/etykietowania.

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

Ten wykres to tylko przykład wygląda nie tak jak moje rzeczywiste wykresy wyglądają jak ... moje prawdziwe wykresy mogą mieć każdą Wartość koloru RGB w nich. Wiem, jak utworzyć wykres, ja po prostu nie wiem jak umieścić oś/Znakowanie na BufferImage że utworzonej

+0

Czy możesz utworzyć łącze do 'png'? Czy masz oryginalne dane? – trashgod

+0

Coś podobnego do tego http://www.goldb.org/goldblog/cmg_images/pylot_latency_sample.png ale będzie to tylko niebieskie i białe punkty w png – Grammin

+0

Czy na pewno chcesz zmienić istniejący obraz? Czy istniejące dane są ważne? Dlaczego nie utworzyć nowego wykresu przypominającego obraz? – trashgod

Odpowiedz

14

Nie sądzę, że modyfikowanie statycznego obrazu będzie działać bardzo dobrze, ponieważ nieuchronnie doprowadzi do błędów rejestracji i niedopasowanych stylów. Zamiast tego włącz jakiekolwiek renderowanie do tworzenia wykresu. Korzystając z podejścia przedstawionego poniżej, można objaśnić kilka sposobów dostosowywania renderowanych kształtów, kolorów i osi zgodnie z potrzebami.

Dodatek: aby pokolorować pojedyncze elementy, interfejs API zaleca podejście pokazane jako here, w którym niestandardowy mechanizm renderowania zastępuje getItemPaint(). Color.getHSBColor() służy do tworzenia pełnego spektrum kolorów.

Response Time chart

Oto oryginał, domyślny renderer dla porównania:

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

Dziękujemy za bardzo szczegółowy przykład kodu! Jak chciałbym zrobić coś w stylu: 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

Domyślam się, że moim głównym problemem jest uzyskanie poprawnych kolorów na wykresie? – Grammin

+0

świetna odpowiedź, naprawdę – mKorbel

0

czytałem obraz w BufferedImage a następnie użyj drawXxxx() metody na zdjęcie użytkownika Instancja Graphics.

Następnie wpisz ten obraz z powrotem do pliku lub wyświetl go w jakimś gui.

+0

Mam obraz w zbuforowanym obrazie, ale nie wiem, jak ciężko będzie go narysować etykiety i linie zakresu/domeny – Grammin

0

O ile się domyślam, byłoby to bardzo trudne. Po przygotowaniu obrazu możesz narysować coś jeszcze na nim, ale jak obliczyć jednostkę, aby była proporcjonalna do obrazu? Jak układać cały obraz później? Dzięki narzędziu do tworzenia wykresów, takim jak jfreechart, masz dużo swobody w zakresie gry z etykietami, osiami i jednostkami. Ale jeśli chodzi o ich rysowanie po utworzeniu wykresu, rzeczy będą bardzo skomplikowane. Nie mam pojęcia, dlaczego chcesz samemu narysować oś lub czy zamierzasz wyświetlać te wykresy w Internecie. Zauważyłem, że wykresy wygenerowane za pomocą jfreechart czasami nie wyglądają bardzo ładnie na stronach internetowych - tekst wygląda rozmytego, a kolor czcionki nie pasuje do innego tekstu na tej samej stronie.

Jeśli zamierzasz umieścić je na stronach internetowych, innym rozwiązaniem byłoby użycie JavaScript do pobierania danych z serwera i rysowania wykresu w locie po stronie klienta.

3

myślę bibliotekę JFreeChart jest właściwym sposobem implementuje raport.

Ale jeśli szukasz kodu do narysowania jakiejś etykiety na obrazku, oto jest.

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

Nie używam jfreechart, używamy Jide, dostają jakąś uroczą bibliotekę wykresów. Podoba mi się, oprócz ceny, ale szef zapłacił i tak. Możesz zobaczyć zrzut ekranu tutaj: http://www.jidesoft.com/products/charts.htm

Powiązane problemy