2012-02-21 8 views
6

devo:
1.) spostare l'origine ed anche ruotare il piano delle coordinate in modo che i valori x progrediscono valori y destrorsi e progredire verso l'alto dalla nuova origine (che deve essere l'angolo in basso a sinistra del rettangolo interno, blu nel codice sottostante). Questo mi consentirà di tracciare punti in coppie di coordinate x, y nel codice qui sotto.
2.) stampare etichette ruotate per i segni di graduazione sull'asse y del grafico dei dati.rotante coordinate aereo per dati e testo in Java

Il seguente codice imposta questo problema. Funziona, tranne per due problemi:
1.) i punti dati vengono tracciati con l'angolo in alto a sinistra mentre i valori di origine e y scendono verso il basso
2.) le etichette per i segni di graduazione sull'asse y sullo schermo non viene visualizzato

Qualcuno può mostrarmi come risolvere il codice riportato di seguito in modo che risolva questi due problemi e faccia ciò che descrive il primo paragrafo sopra?

Il codice si trova nelle seguenti due file java:

DataGUI.java

import java.awt.*; 
import java.util.ArrayList; 
import javax.swing.*; 

class DataGUI extends JFrame{ 
DataGUI() { 
    super("X,Y Plot"); 
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    this.setPreferredSize(new Dimension(800, 400)); 
    this.pack(); 
    this.setSize(new Dimension(800, 600)); 
    this.setLocationRelativeTo(null); 


    setLayout(new GridLayout()); 
    ArrayList<Double> myDiffs = new ArrayList<Double>(); 
      myDiffs.add(25.0); 
      myDiffs.add(9.0); 
      myDiffs.add(7.0); 
      myDiffs.add(16.0); 
      myDiffs.add(15.0); 
      myDiffs.add(6.0); 
      myDiffs.add(2.0); 
      myDiffs.add(8.0); 
      myDiffs.add(2.0); 
      myDiffs.add(27.0); 
      myDiffs.add(14.0); 
      myDiffs.add(12.0); 
      myDiffs.add(19.0); 
      myDiffs.add(10.0); 
      myDiffs.add(11.0); 
      myDiffs.add(8.0); 
      myDiffs.add(19.0); 
      myDiffs.add(2.0); 
      myDiffs.add(16.0); 
      myDiffs.add(5.0); 
      myDiffs.add(18.0); 
      myDiffs.add(23.0); 
      myDiffs.add(9.0); 
      myDiffs.add(4.0); 
      myDiffs.add(8.0); 
      myDiffs.add(9.0); 
      myDiffs.add(3.0); 
      myDiffs.add(3.0); 
      myDiffs.add(9.0); 
      myDiffs.add(13.0); 
      myDiffs.add(17.0); 
      myDiffs.add(7.0); 
      myDiffs.add(0.0); 
      myDiffs.add(2.0); 
      myDiffs.add(3.0); 
      myDiffs.add(33.0); 
      myDiffs.add(23.0); 
      myDiffs.add(26.0); 
      myDiffs.add(12.0); 
      myDiffs.add(12.0); 
      myDiffs.add(19.0); 
      myDiffs.add(14.0); 
      myDiffs.add(9.0); 
      myDiffs.add(26.0); 
      myDiffs.add(24.0); 
      myDiffs.add(13.0); 
      myDiffs.add(19.0); 
      myDiffs.add(2.0); 
      myDiffs.add(7.0); 
      myDiffs.add(28.0); 
      myDiffs.add(15.0); 
      myDiffs.add(2.0); 
      myDiffs.add(5.0); 
      myDiffs.add(17.0); 
      myDiffs.add(2.0); 
      myDiffs.add(16.0); 
      myDiffs.add(19.0); 
      myDiffs.add(2.0); 
      myDiffs.add(31.0); 
    DataPanel myPP = new DataPanel(myDiffs,this.getHeight(),this.getWidth()); 
    this.add(myPP); 
    this.setVisible(true);// Display the panel. 
} 
public static void main(String[] args){ 
    DataGUI myDataGUI = new DataGUI(); 
    myDataGUI.setVisible(true); 
} 
} 

DataPanel.java (Nota: ho modificato il codice qui sotto per includere i suggerimenti di trashgod, ma lo fa ancora non funziona.)

import java.awt.*; 
import java.awt.geom.AffineTransform; 
import javax.swing.*; 
import java.text.DecimalFormat; 
import java.text.NumberFormat; 
import java.util.*; 

class DataPanel extends JPanel { 
Insets ins; // holds the panel's insets 
ArrayList<Double> myDiffs; 
double maxDiff = Double.NEGATIVE_INFINITY; 
double minDiff = Double.POSITIVE_INFINITY; 
double maxPlot; 

DataPanel(ArrayList<Double> Diffs, int h, int w){ 
    setOpaque(true);// Ensure that panel is opaque. 
    setPreferredSize(new Dimension(w, h)); 
    setMinimumSize(new Dimension(w, h)); 
    setMaximumSize(new Dimension(w, h)); 
    myDiffs = Diffs; 
    repaint(); 
    this.setVisible(true); 
} 

protected void paintComponent(Graphics g){// Override paintComponent() method. 
    super.paintComponent(g); 
    //get data about plotting environment and about text 
    int height = getHeight(); 
    int width = getWidth(); 
    ins = getInsets(); 
    Graphics2D g2d = (Graphics2D)g; 
    FontMetrics fontMetrics = g2d.getFontMetrics(); 
    String xString = ("x-axis label"); 
    int xStrWidth = fontMetrics.stringWidth(xString); 
    int xStrHeight = fontMetrics.getHeight(); 
    String yString = "y-axis label"; 
    int yStrWidth = fontMetrics.stringWidth(yString); 
    int yStrHeight = fontMetrics.getHeight(); 
    String titleString ="Title of Graphic"; 
    int titleStrWidth = fontMetrics.stringWidth(titleString); 
    int titleStrHeight = fontMetrics.getHeight(); 
    int leftMargin = ins.left; 
    //set parameters for inner rectangle 
    int hPad=10; 
    int vPad = 6; 
    int testLeftStartPlotWindow = ins.left+5+(3*yStrHeight); 
    int testInnerWidth = width-testLeftStartPlotWindow-ins.right-hPad; 
    getMaxMinDiffs(); 
    getMaxPlotVal(); 
    double increment = 5.0; 
    int numTicks = (int)(maxPlot/increment);//will use numTicks for: remainder, leftStartPlotWindow, innerRectangle+labels+tickmarks 
    int remainder = testInnerWidth%numTicks; 
    int leftStartPlotWindow = testLeftStartPlotWindow-remainder; 
    System.out.println("remainder is: "+remainder); 
    int bottomPad = (3*xStrHeight)-vPad; 
    int blueTop = ins.bottom+(vPad/2)+titleStrHeight; 
    int blueHeight = height-bottomPad-blueTop; 
    int blueWidth = blueHeight; 
    int blueBottom = blueHeight+blueTop; 

    //plot outer rectangle 
    g.setColor(Color.red); 
    int redWidth = width-leftMargin-1; 
    g.drawRect(leftMargin, ins.bottom, redWidth, height-ins.bottom-1); 
    //write top label 
    g.setColor(Color.black); 
    g.drawString(titleString, leftStartPlotWindow+((blueWidth/2)-(titleStrWidth/2)), titleStrHeight); 
    // fill, then plot, inner rectangle 
    g.setColor(Color.white); 
    g.fillRect(leftStartPlotWindow, blueTop, blueWidth, blueHeight); 
    g.setColor(Color.blue); 
    g.drawRect(leftStartPlotWindow, blueTop, blueWidth, blueHeight); 
    //scale the diffs to fit window 
    double Scalar = blueWidth/maxPlot; 
    ArrayList<Double> scaledDiffs = new ArrayList<Double>(); 
    for(int e = 0;e<myDiffs.size();e++){scaledDiffs.add(myDiffs.get(e)*Scalar);} 
    //plot the scaled Diffs 
    AffineTransform at = g2d.getTransform();//save the graphics context's transform 
    g2d.translate(leftStartPlotWindow, blueTop);//translate origin to bottom-left corner of blue rectangle 
    g2d.scale(1, -1);//invert the y-axis 
    for(int w = 0;w<scaledDiffs.size();w++){ 
     if(w>0){ 
      double prior = scaledDiffs.get(w-1); 
      int priorInt = (int)prior; 
      double current = scaledDiffs.get(w); 
      int currentInt = (int)current; 
      g2d.drawOval(priorInt, currentInt, 4, 4); 
     } 
    } 
    g2d.setTransform(at);//restore the transform for conventional rendering 
    //write x-axis label 
    g.setColor(Color.red); 
    g.drawString(xString, leftStartPlotWindow+((blueWidth/2)-(xStrWidth/2)), height-ins.bottom-vPad); 
    //write y-axis label 
    g2d.rotate(Math.toRadians(-90), 0, 0);//rotate text 90 degrees counter-clockwise 
    g.drawString(yString, -(height/2)-(yStrWidth/2), yStrHeight); 
    g2d.rotate(Math.toRadians(+90), 0, 0);//rotate text 90 degrees clockwise 
    // draw tick marks on x-axis 
    NumberFormat formatter = new DecimalFormat("#0.0"); 
    double k = (double)blueWidth/(double)numTicks; 
    double iteration = 0; 
    for(int h=0;h<=numTicks;h++){ 
     int xval = (int)(h*k); 
     g.setColor(Color.red); 
     g.drawLine(leftStartPlotWindow+xval, blueBottom+2, leftStartPlotWindow+xval, blueBottom+(xStrHeight/2));//draw tick marks 
     g.drawString(formatter.format(iteration),leftStartPlotWindow+xval-(fontMetrics.stringWidth(Double.toString(iteration))/2),blueBottom+(xStrHeight/2)+13); 
     iteration+=increment; 
    } 
    // draw tick marks on y-axis 
    iteration = 0; 
    for(int h=0;h<=numTicks;h++){ 
     int yval = (int)(h*k); 
     g.setColor(Color.red); 
     g.drawLine(leftStartPlotWindow-2, blueBottom-yval, leftStartPlotWindow-(yStrHeight/2), blueBottom-yval);//draw tick marks 
     g2d.rotate(Math.toRadians(-90), 0, 0);//rotate text 90 degrees counter-clockwise 
     g.drawString(formatter.format(iteration),leftStartPlotWindow-2,blueBottom-(fontMetrics.stringWidth(Double.toString(iteration))/2)); 
     g2d.rotate(Math.toRadians(+90), 0, 0);//rotate text 90 degrees clockwise 
     iteration+=increment; 
    } 
} 
void getMaxMinDiffs(){// get max and min of Diffs 
    for(int u = 0;u<myDiffs.size();u++){ 
     if(myDiffs.get(u)>maxDiff){maxDiff = myDiffs.get(u);} 
     if(myDiffs.get(u)<minDiff){minDiff = myDiffs.get(u);} 
    } 
} 
void getMaxPlotVal(){ 
    maxPlot = maxDiff; 
    maxPlot += 1;//make sure maxPlot is bigger than the max data value 
    while(maxPlot%5!=0){maxPlot+=1;}//make sure maxPlot is a multiple of 5 
} 
} 

Inoltre, come sempre, link ad articoli o tutorial sull'argomento sono molto apprezzati.

+0

correlato al problema a portata di mano, ma i dati aggiunti al ArrayList devono essere tenuti in un file di dati, non hard-coded nel programma. –

+2

@Hovercraft Full Of Eels, sì, lo so. In effetti, i dati sono il risultato di alcune operazioni di array ed è molto più lungo del set di dati sopra riportato. Tuttavia, l'ho caricato come ho fatto sopra in modo che fosse più facilmente riproducibile per le persone su questo sito. – CodeMed

+1

Considerare 'Elenco myDiffs = new ArrayList (Arrays.asList (25.0, 9.0, 7.0, ...))'. – trashgod

risposta

2

Ci scusiamo per la risposta un po 'incompleta, ma questo potrebbe far girare il tuo ingranaggio. Java disegna le cose come le hai descritte: considera l'angolo in alto a sinistra dello schermo come 0, 0 e disegna x crescente verso destra e y crescente verso il basso. Se si effettua la linea che indica

g2d.drawOval(priorInt, currentInt, 4, 4); 

in

g2d.drawOval(blueWidth - priorInt, blueHeight - currentInt, 4, 4); 

dovrebbe dare i risultati corretti per il primo numero. Ho bisogno di qualche informazione in più sul secondo problema per aiutarti con quello. Sono appena fuori dallo schermo o sono attratti da qualcos'altro? Prova a girare + se e -s in giro per vedere se riesci a ottenere il risultato corretto, se così fosse.

+0

Grazie per il suggerimento. Ho apportato la modifica e ho provato a eseguire il codice, ma ne traccia uno al di fuori del rettangolo blu, il che dimostra che non è correttamente riposizionando i punti dati. Puoi vedere da te che, se esegui il codice con il tuo cambiamento, c'è un punto dati a sinistra del bordo sinistro del rettangolo blu, circa il 70% del modo in cui lo schermo. Ciò significa che anche ogni punto viene tracciato in modo errato, anche se si trova all'interno della casella blu. Per quanto riguarda le etichette dei segni di tic, dovrebbero essere posizionate in modo simile alle etichette dell'asse x. +1 per aver cercato di aiutare. – CodeMed

+0

Prova a utilizzare g2d.drawOval (priorInt, -currentInt, 4, 4); Sono un po 'alla cieca perché non sto eseguendo il codice che sto suggerendo. Mi dispiace, ma sono pigro per scrivere un wrapper JPanel = P. –

+0

L'unica cosa che posso vedere male con il codice di disegno dell'etichetta dell'asse y è che si può semplicemente disegnare all'interno della scatola rossa. Prova a cambiare 'g2d.setColor (Color.red)' a 'g2d.setColor (Color.green)' –

10

Un approccio è mostrato in SineTest. In linea,

  1. Salvare la trasformazione del contesto grafico.

    Graphics2D g2d = (Graphics2D) g; 
    AffineTransform at = g2d.getTransform(); 
    
  2. Traduci l'origine al centro.

    g2d.translate(w/2, h/2); 
    
  3. invertito il y -axis.

    g2d.scale(1, -1); 
    
  4. Rendering tramite coordinate cartesiane.

  5. Ripristina la trasformazione per rendering convenzionale.

    g2d.setTransform(at); 
    

enter image description here

+0

+1 Grazie. Seguirò attentamente il tuo suggerimento. Per favore comprendi che ho esplorato traduzioni, inversioni, trasformazioni affini e simili, se necessario per un po 'di tempo, e mi confondono sempre. Quando ho capito per una domanda, trovo che sono confuso poche settimane dopo quando sorge la necessità per la prossima applicazione. Sei disposto a incorporare i tuoi suggerimenti in codice funzionante nel mio file DataPanel.java qui sopra? Se fossi disposto a farlo, sarei in grado di rivedere attentamente il tuo codice con java api e capire meglio come funziona. – CodeMed

+0

L'esempio citato è completo e illustra una caratteristica essenziale della grafica transform-_order counts_. I segni di intervallo scompaiono perché sono stati ruotati fuori dalla vista. Altro [qui] (http://stackoverflow.com/q/3843105/230513). – trashgod

+0

Ho rivisto il tuo codice e i riferimenti che hai citato. Ho anche apportato le tue modifiche suggerite, ma ora non si tratta semplicemente di tracciare tutti tranne uno dei punti. Ho mostrato il codice revisionato nella mia pubblicazione originale qui sopra, inclusi i tuoi suggerimenti, in modo che il problema rimanente possa essere ricreato. Sei disposto a mostrarmi come correggere il mio codice rivisto qui sopra in modo che faccia ciò che il mio post originale afferma che sto cercando di fare? Grazie. – CodeMed