下面的代码绘制了一些简单的x-y数据,但它有两个我不知道如何解决的问题。
首先,它绘制了一些数据点的负值,这意味着在x轴下方向南延伸的线。由于数据点是随机选择的,因此您可能需要稍微调整帧的大小,以便以显示此错误的方式查看要绘制的新随机数。所有数据值都是正数,因此我希望所有偏转都向北投射到蓝色底部标记线上方,并且我需要确保没有偏转在蓝色底部标记线下方向南延伸。
其次,y轴标签在屏幕上占用太多空间。它需要旋转-90度。但是,我看到的所有示例都涉及使用graphics2d对象旋转整个面板。我不想旋转整个面板。相反,我只想旋转y轴标签的文本。
有谁能告诉我如何更改下面的代码来解决这两个具体问题?
代码位于以下两个文件中:
GUI.java
import java.awt.*;
import javax.swing.*;
class GUI{
GUI() {
// Create a new JFrame container.
JFrame jfrm = new JFrame("X-Y Plot");
// Specify FlowLayout for the layout manager.
jfrm.getContentPane().setLayout(new FlowLayout());
int frameHeight = 400;
int frameWidth = 300;
// Give the frame an initial size.
jfrm.setSize(frameWidth, frameHeight);
// Terminate the program when the user closes the application.
jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Create a text-based label.
JVertLabel myVLabel = new JVertLabel("y-axis label");
int width = myVLabel.WIDTH;
PaintPanel myPP = new PaintPanel(frameWidth-width-50-20,frameHeight-70);
jfrm.add(myPP);
jfrm.add(myVLabel);// Add the label to the frame.
// Display the frame.
jfrm.setVisible(true);
}
public static void main(String args[]) {
// Create the frame on the event dispatching thread.
SwingUtilities.invokeLater(new Runnable() {public void run(){new GUI();}});
}
public class JVertLabel extends JComponent {
private String text;
public JVertLabel(String s) {
text = s;
}//constructor
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.rotate(Math.toRadians(-90));
g2d.drawString(text, 0, 0);
}
}
}
PaintPanel.java
import java.awt.*;
import javax.swing.*;
import java.util.*;
class PaintPanel extends JPanel {
Insets ins; // holds the panel's insets
Random rand; // used to generate random numbers
PaintPanel(int w, int h) {
setOpaque(true);// Ensure that panel is opaque.
setPreferredSize(new Dimension(w, h));// Set preferred dimension as specfied.
rand = new Random();
}
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;
Font font = new Font("Serif", Font.PLAIN, 12);
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();
int leftStartPlotWindow = ins.left + 5 + yStrWidth;
int hPad = 3;
// Fill panel by plotting random data in a bar graph.
for (int i = leftStartPlotWindow + hPad; i <= width - leftStartPlotWindow - hPad + yStrWidth + 1; i += 4) {
int h = Math.abs(rand.nextInt(height - ins.bottom));//Get rand# betw/0 and max height of drawing area.
// If generated value w/in or too close to border, change it to just outside border.
if (h <= ins.top) {
h = ins.top + 1;
}
g.drawLine(i, Math.abs(height - ins.bottom - xStrHeight - 5), i, h);// Draw a line that represents data.
}
g.setColor(Color.blue);
g.drawRect(leftStartPlotWindow, ins.bottom + 2, width - leftStartPlotWindow - ins.right - hPad, height - xStrHeight - 6);
g.setColor(Color.red);
g.drawRect(ins.left, ins.bottom, width - ins.left - 1, height - ins.bottom - 1);
g.drawString(xString, (width / 2) - (xStrWidth / 2), height - ins.bottom - 6);
g.drawString(yString, ins.left, height / 2);
}
}
答案 0 :(得分:3)
所有数据值都是正数,因此我希望所有偏转都向北投射到蓝色底部标记线上方,我需要确保没有偏转向南延伸到蓝色底部标记线下方。
您需要计算随机高度,以便所有值都适合可用空间。所以计算结果如下:
int randomHeight = panelHeight - offset.top - offset.bottom - heightForTheXAxisText;
然后您不必担心负值或超出面板边界的线的顶部。
我见过的所有例子都涉及使用graphics2d对象旋转整个面板。我不想旋转整个面板。相反,我只想旋转y轴标签的文本。
设置Graphics对象的旋转,绘制文本,然后将Graphics对象的旋转恢复为0.
或者,您从当前Graphics对象创建一个新的Graphcis对象,然后应用旋转,绘制文本然后处理temporaray Graphics对象。
答案 1 :(得分:2)
JFreeChart
解决了这两个问题,如example所示。
在您的示例中,
在尝试渲染数据模型之前,您必须先创建数据模型。然后,您可以扫描 min 和 max 以确定range轴的限制。 List<Double>
可能是合适的选择。
您可以通过更改图形上下文AffineTransform
来旋转范围标签,如RotateText
所示。