Я программирую простую диаграмму, с помощью которой вы можете отображать некоторые точки по осям 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
, но не внес никаких изменений.