2012-02-21 32 views
6

Tôi cần phải:
1.) di chuyển gốc và xoay mặt phẳng tọa độ sao cho giá trị x tiến tới các giá trị y và giá trị tiến lên từ gốc mới (cần là góc dưới cùng bên trái của hình chữ nhật màu xanh bên trong trong mã bên dưới). Điều này sẽ cho phép tôi vẽ điểm tại các cặp tọa độ x, y trong đoạn mã dưới đây.
2.) nhãn xoay ô cho các dấu tic trên trục y của ô dữ liệu.xoay tọa độ mặt phẳng cho dữ liệu và văn bản trong Java

Mã bên dưới thiết lập sự cố này. Nó hoạt động, ngoại trừ hai vấn đề:
1.) các điểm dữ liệu đang được vẽ với góc trên bên trái khi nguồn gốc và giá trị y giảm dần xuống
2.) nhãn cho dấu tic trên trục y không được vẽ trên màn hình

Bất kỳ ai cũng có thể chỉ cho tôi cách sửa mã bên dưới để nó khắc phục hai vấn đề này và làm đoạn đầu tiên ở trên mô tả?

Mã này là trong hai tập tin java sau:

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 (Lưu ý: Tôi chỉnh sửa mã bên dưới để thêm gợi ý trashgod, nhưng nó vẫn không không hoạt động.)

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

Ngoài ra, như mọi khi, các liên kết đến bài viết hoặc hướng dẫn về chủ đề được đánh giá cao.

+0

Không liên quan đến các vấn đề trong tầm tay, nhưng các dữ liệu thêm vào ArrayList nên được tổ chức trong một tập tin dữ liệu, không mã hóa cứng trong chương trình. –

+2

@Hovercraft Full Of Eels, Vâng, tôi biết. Trong thực tế, dữ liệu là kết quả của một số hoạt động mảng và dài hơn nhiều so với tập dữ liệu ở trên. Tuy nhiên, tôi tải nó theo cách tôi đã làm ở trên để nó sẽ dễ dàng tái tạo hơn cho những người trên trang web này. – CodeMed

+1

Hãy xem xét 'Danh sách myDiffs = new ArrayList (Arrays.asList (25.0, 9.0, 7.0, ...)) '. – trashgod

Trả lời

2

Xin lỗi vì câu trả lời không đầy đủ, nhưng điều này có thể làm cho bánh răng của bạn quay. Java vẽ những thứ theo cách bạn mô tả chúng: Nó xem góc trên bên trái của màn hình là 0, 0 và vẽ x tăng lên bên phải và y tăng dần xuống. Nếu bạn thực hiện các dòng đó khẳng định

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

vào

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

nó nên đạt được kết quả chính xác cho vấn đề đầu tiên của bạn. Tôi cần thêm một chút thông tin về vấn đề thứ hai để giúp bạn với điều đó mặc dù. Có phải họ vừa rời khỏi màn hình hay đang bị lôi kéo bởi cái gì khác? Hãy thử flipping + s và -s xung quanh để xem bạn có thể nhận được kết quả chính xác nếu đúng như vậy không.

+0

Cảm ơn bạn đã đề xuất. Tôi đã thực hiện thay đổi và cố gắng chạy mã, nhưng nó vẽ một bên ngoài hình chữ nhật màu xanh, cho thấy rằng nó không đúng định vị lại các điểm dữ liệu. Bạn có thể thấy cho chính mình rằng, nếu bạn chạy mã với sự thay đổi của bạn, có một điểm dữ liệu ở bên trái của cạnh trái của hình chữ nhật màu xanh, khoảng 70% của con đường lên màn hình. Điều đó có nghĩa là mọi điểm cũng được vẽ không chính xác, ngay cả khi chúng nằm trong hộp màu xanh dương. Đối với nhãn hiệu tic, chúng được cho là tương tự như nhãn x trục. 1 để cố gắng giúp đỡ. – CodeMed

+0

Hãy thử sử dụng g2d.drawOval (priorInt, -currentInt, 4, 4); Tôi sắp bị mù vì tôi không chạy mã tôi đang đề xuất. Xin lỗi về điều đó, nhưng tôi lười biếng để viết một wrapper JPanel = P. –

+0

Điều duy nhất tôi có thể thấy sai với mã vẽ nhãn trục y của bạn là bạn có thể chỉ vẽ bên trong hộp màu đỏ của bạn. Hãy thử thay đổi 'g2d.setColor (Color.red)' thành 'g2d.setColor (Color.green)' –

10

Một cách tiếp cận được hiển thị trong SineTest. Tóm tắt,

  1. Lưu biến đổi ngữ cảnh đồ họa.

    Graphics2D g2d = (Graphics2D) g; 
    AffineTransform at = g2d.getTransform(); 
    
  2. Dịch gốc thành tâm.

    g2d.translate(w/2, h/2); 
    
  3. Invert các y trục.

    g2d.scale(1, -1); 
    
  4. Hiển thị bằng cách sử dụng tọa độ Descartes.

  5. Khôi phục biến đổi để hiển thị thông thường.

    g2d.setTransform(at); 
    

enter image description here

+0

+1 Cảm ơn bạn. Tôi sẽ cẩn thận đi qua đề nghị của bạn. Hãy hiểu rằng tôi đã khám phá bản dịch, đảo ngược, biến đổi affine, và những thứ tương tự khi cần thiết trong một thời gian, và chúng luôn gây nhầm lẫn cho tôi. Khi tôi tìm ra một ứng dụng, tôi thấy tôi bối rối một vài tuần sau đó khi cần thiết cho ứng dụng tiếp theo. Bạn có sẵn sàng đưa các đề xuất của bạn vào mã hoạt động trong tệp DataPanel.java của tôi ở trên không? Nếu bạn đã sẵn sàng để làm điều đó, tôi sẽ có thể xem xét cẩn thận mã của bạn với api java và hiểu rõ hơn cách hoạt động của nó. – CodeMed

+0

Ví dụ được trích dẫn hoàn chỉnh và minh họa một tính năng thiết yếu của biến đổi đồ họa — _order count_. Dấu phạm vi của bạn biến mất vì chúng đã bị loại bỏ khỏi tầm nhìn. Thêm [tại đây] (http://stackoverflow.com/q/3843105/230513). – trashgod

+0

Tôi đã xem xét mã của bạn và các tài liệu tham khảo bạn đã trích dẫn. Tôi cũng đã thực hiện thay đổi được đề xuất của bạn, nhưng bây giờ nó chỉ đơn giản là không âm mưu tất cả, nhưng một trong những điểm. Tôi đã hiển thị mã đã sửa đổi trong bài đăng gốc ở trên, bao gồm các đề xuất của bạn, để vấn đề hiện tại còn lại có thể được tạo lại. Bạn có sẵn sàng chỉ cho tôi cách sửa mã đã sửa đổi của tôi ở trên để nó thực hiện những gì bài đăng gốc của tôi nói rằng tôi đang cố gắng làm không? Cảm ơn bạn. – CodeMed

Các vấn đề liên quan