我正在编写一个简单的图,可以在x,y轴上显示一些点。
public class GraphPlotter extends JPanel {
private static final long serialVersionUID = 1L;
/** Default frame size X for frame in pixels */
private final int DEFAULT_FRAME_SIZE_X = 800;
/** Default frame size Y for frame in pixels */
private final int DEFAULT_FRAME_SIZE_Y = 600;
/** Padding to Frame */
private final int PAD = 30;
/** Radius of dot */
private final int DOT_RADIUS = 3;
/** Padding of label */
private final int LABEL_PAD = 10;
/** Height of label */
private final int LABEL_HEIGHT = 10;
/** Width of label */
private final int LABEL_WIDTH = 100;
/** Max value for x to print */
private int maxValueForX;
/** Scale factor depending to y*/
private int maxValueForY;
/** Label for the x axis */
private String labelForX = "time";
/** Label for the y axis */
private String labelForY;
/**
* List with points to draw. It holds the y coordinates of points. x
* coordinates are spaced
*/
private List<Integer> dataPoints = new ArrayList<>();
/**
*
* Constructor of this class
*
*/
public GraphPlotter(ArrayList<Integer> dataPoints, String labelForY) {
this.dataPoints = dataPoints;
this.maxValueForX = dataPoints.size();
this.maxValueForY = Collections.max(dataPoints);
this.labelForY = labelForY;
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(this);
f.setSize(this.DEFAULT_FRAME_SIZE_X + PAD, this.DEFAULT_FRAME_SIZE_Y + PAD);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
/** method that draws the points and lines between the points */
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
int w = getWidth();
int h = getHeight();
// add labels
JLabel jLabelY = new JLabel(labelForY);
JLabel jLabelX = new JLabel(labelForX);
jLabelY.setSize(LABEL_WIDTH, LABEL_HEIGHT);
jLabelY.setLocation(LABEL_PAD, LABEL_PAD);
add(jLabelY);
jLabelX.setSize(LABEL_WIDTH, LABEL_HEIGHT);
jLabelX.setLocation(w - LABEL_WIDTH - LABEL_PAD, h - LABEL_HEIGHT - LABEL_PAD);
jLabelX.setHorizontalAlignment(SwingConstants.RIGHT);
add(jLabelX);
// add axis
g2.drawLine(PAD, PAD, PAD, h - PAD);
g2.drawLine(PAD, h - PAD, w - PAD, h - PAD);
double xScale = (w - 2 * PAD) / (dataPoints.size() + 1);
double yScale = (h - 2 * PAD) / this.maxValueForY;
int x0 = PAD;
int y0 = h - PAD;
// draw the points as small circles
g2.setPaint(Color.blue);
for (int i = 0; i < dataPoints.size(); i++) {
int x = x0 + (int) (xScale * (i + 1));
int y = y0 - (int) (yScale * dataPoints.get(i));
g2.fillOval(x - DOT_RADIUS, y - DOT_RADIUS, 2 * DOT_RADIUS,
2 * DOT_RADIUS);
}
}
/** Size of List */
private int getSizeOfDataPoints() {
return dataPoints.size();
}
/** Deletes last DataPoint in List */
private void deleteLastDataPoint() {
dataPoints.remove(0);
}
/**
* Ad point and repaint graph.
*
* @param point to draw (y-coord)
*/
public void add(int point) {
if (getSizeOfDataPoints() > this.maxValueForX) {
deleteLastDataPoint();
}
dataPoints.add(point);
this.repaint();
}
public static void main(String[] args) {
ArrayList<Integer> scores = new ArrayList<>();
Random random = new Random();
for (int i = 0; i < 50; i++) {
scores.add(random.nextInt(10));
}
String labelForY = "throughput";
GraphPlotter graphPlotter = new GraphPlotter(scores, labelForY);
graphPlotter.add(5);
}
标签显示在应用程序启动时。如果我调整应用程序窗口的大小,标签将显示在整个窗口中。 (请参见屏幕截图)
如何避免标签重复出现? 我假设在重新绘制窗口后,程序在面板中添加了相同的标签。如果我写
add(jLabelY);
repaint();
在paintComponent()
方法中,该错误在应用程序启动时发生。
我还尝试将面板放入FlowLayout
,但未做任何更改。
答案 0 :(得分:2)
paintComponent()
几乎可以通过Swing调用(无论何时需要重新绘制组件;例如,在调整大小时)。因此,通常应无副作用。但是,您使用paintComponent
至add()
标签作为面板的子级,但从未删除。因此,每次重新绘制面板时,都会向其子级添加两个标签。 super.paintComponent()
然后将它们全部绘制。
一种解决方案是将两个标签保留为面板的字段,并且仅在paintComponent
中(在调用super.paintComponent()
之前)更新它们的位置