我有一个数据集,我在下面的代码中定义的矩形空间内绘图。数据集的长度几乎总是不同于需要绘制数据集的屏幕空间的像素宽度。缩放数据以适合像素空间
我的问题是,我需要一种有效的方式将数据集的图形分布在整个绘图空间的宽度上。
正如您从下面发布的代码中看到的,数据正在(不正确)绘制在矩形宽度的子集中。如果编译代码并手动重新调整框架大小几次,则会看到数据图的宽度相对于蓝色内部矩形的宽度随着框架宽度的变化而变化。为了更清楚地说明这一点,下面的代码还绘制了两条绿色垂直线,一条在数据集图形的开头和另一端。如果代码正常工作,垂直绿线应该只位于蓝色内矩形的开始和结尾,并且它们之间的尖峰应该与内部蓝色矩形的起点和终点之间的适当的百分比距离(30 %和70%,分别对应于指数120/400和280/400)。但是,正如您所看到的那样,第二条绿色垂直线总是不合适,而第一条绿色线似乎始终处于其正确位置,并且数据卡的位置与(错位)绿色垂直标记相对,而不是相对于内部蓝色矩形的左右边缘正确放置,它应与(正确放置的)绿色垂直线重叠。
任何人都可以告诉我如何解决下面的代码,以便它平均分配宽度的内部蓝色矩形的数据图的宽度?
我认为问题出在hstep变量中,并且我在下面的DataPanel.java代码中标记了我认为问题代码与评论中的所有CAPS一致的地方。
的代码在以下两个文件:
DataGUI.java
import java.awt.*;
import javax.swing.*;
class DataGUI{
DataGUI() {
JFrame jfrm = new JFrame("X-Y Plot");// Create a new JFrame container.
jfrm.getContentPane().setLayout(new GridLayout(1,1));// Specify FlowLayout for the layout manager.
int frameHeight = 500;
int frameWidth = 767;
jfrm.setSize(frameWidth, frameHeight);// Give the frame an initial size.
jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// Terminate program when user closes application.
int len = 400;
double[] data = new double[len];
for(int d=0;d<data.length;d++){
if(d==120||d==280){data[d]=45;}
else{data[0]=0;}
}
DataPanel myDataPanel = new DataPanel(data);
jfrm.add(myDataPanel);
jfrm.setVisible(true);// Display the frame.
}
public static void main(String args[]) {
// Create frame on event dispatching thread.
SwingUtilities.invokeLater(new Runnable() {public void run(){new DataGUI();}});
}
}
DataPanel.java
import java.awt.*;
import javax.swing.*;
import java.text.NumberFormat;
class DataPanel extends JPanel {
Insets ins; // holds the panel's insets
int len = 400;// for testing only. will throw error if you do not link this to an array length.
double[] plotData;
double xScale;
DataPanel(double[] myData) {
setOpaque(true);// Ensure that panel is opaque.
plotData = myData;
}
protected void paintComponent(Graphics g){// Override paintComponent() method.
super.paintComponent(g);// Always call superclass method first.
int height = getHeight();// Get height of component.
int width = getWidth();// Get width of component.
ins = getInsets();// Get the insets.
// Get dimensions of text
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();
//get margins
int leftMargin = ins.left;
//set parameters for inner rectangle
int hPad=10;
int vPad = 6;
int numYticks = 10;
int testLeftStartPlotWindow = ins.left+5+(3*yStrHeight);
int testInnerWidth = width-testLeftStartPlotWindow-ins.right-hPad;
int remainder = testInnerWidth%numYticks;
int leftStartPlotWindow = testLeftStartPlotWindow-remainder;
System.out.println("remainder is: "+remainder);
int blueWidth = testInnerWidth-remainder;
int endIndex = leftStartPlotWindow+blueWidth;
int blueTop = ins.bottom+(vPad/2)+titleStrHeight;
int bottomPad = (3*xStrHeight)-vPad;
int blueHeight = height-bottomPad-blueTop;
int blueBottom = blueHeight+blueTop;
g.setColor(Color.red);
int redWidth = width-leftMargin-1;
//plot outer rectangle
g.drawRect(leftMargin, ins.bottom, redWidth, height-ins.bottom-1);
System.out.println("blueWidth is: "+blueWidth);
// fill inner rectangle
g.setColor(Color.white);
g.fillRect(leftStartPlotWindow, blueTop, blueWidth, blueHeight);
//write top label
g.setColor(Color.black);
g.drawString(titleString, (width/2)-(titleStrWidth/2), titleStrHeight);
//write x-axis label
g.setColor(Color.red);
g.drawString(xString, (width/2)-(xStrWidth/2), height-ins.bottom-vPad);
g2d.rotate(Math.toRadians(-90), 0, 0);//rotate text 90 degrees counter-clockwise
//write y-axis label
g.drawString(yString, -(height/2)-(yStrWidth/2), yStrHeight);
g2d.rotate(Math.toRadians(+90), 0, 0);//rotate text 90 degrees clockwise
// draw tick marks and data rectangles on x-axis
NumberFormat formatter = NumberFormat.getPercentInstance();
double k = blueWidth/numYticks;
double iteration = 0;
for(int h=0;h<=numYticks;h++){
int xval = (int)(h*k);
//draw tick marks
g.setColor(Color.red);
g.drawLine(leftStartPlotWindow+xval, blueBottom+2, leftStartPlotWindow+xval, blueBottom+(xStrHeight/2));
g.drawString(formatter.format(iteration/10),leftStartPlotWindow+xval-(fontMetrics.stringWidth(Double.toString(iteration/10))/2),blueBottom+(xStrHeight/2)+13);
iteration+=1;
}
//plot data
// I THINK THE PROBLEM IS IN THE NEXT LINE OF CODE, BECAUSE hstep EVALUATES TO EITHER 1 OR 2.
// HOW DO I ALTER THIS SO THAT THE PLOT IS ABLE TO STRETCH ON A SCALAR THAT IS NOT AS COARSE?
double hstep = blueWidth/len;
System.out.println("hstep, len are: "+hstep+", "+len);
for(int h = 1;h<len;h++){
int x2 = leftStartPlotWindow+(int)(h * hstep);
int x1 = leftStartPlotWindow+(int) ((h - 1) * hstep);
int y1 = (blueBottom-(int)plotData[h - 1]);
int y2 = (blueBottom-(int)plotData[h]);
g.drawLine(x1, y1, x2, y2);
g.setColor(Color.green);
if(h==1){
g.drawLine(leftStartPlotWindow+(int)(h*hstep), blueBottom, leftStartPlotWindow+(int)(h*hstep), blueBottom-100);
}
if(h==len-1){
g.drawLine(leftStartPlotWindow+(int)(h*hstep), blueBottom, leftStartPlotWindow+(int)(h*hstep), blueBottom-100);
}
g.setColor(Color.red);
}
// plot inner rectangle
g.setColor(Color.blue);
g.drawRect(leftStartPlotWindow, blueTop, blueWidth, blueHeight);
}
}
+1谢谢您的建议。有没有简单的方法让你提供一些示例代码来说明你所建议的技术? – CodeMed 2012-01-04 22:40:57
谢谢。我将此标记为答案,因为您比其他人更重视这一点。但是,任何读者都可以看到所有三个答案都是正确的。 – CodeMed 2012-01-05 21:56:23