Проблема построения графиков - PullRequest
0 голосов
/ 04 марта 2012

Я создаю линейный график, используя выходные данные из потока, потоки являются имитацией входящего и исходящего счета, который выполняется в течение 52 секунд, и это будет отображаться на линейном графике, как показано ниже, чтобы показать баланс банка над52 секунды!

В настоящее время программа работает нормально, когда я нажимаю кнопку Пуск, точка обновляется, но каждая новая точка помещается на график, а предыдущая исчезает.Как я могу сохранить все точки на графике.

Я бы предположил, что мне нужно создать 2 новые переменные типа int ... prevX и prevY.

enter image description here

import java.awt.*;
import javax.swing.*;

public class DrawPanel extends JPanel {

   private static final int X_AXIS_LENGTH = 700;
   private static final int Y_AXIS_LENGTH = 230; // could be changed
   private static final int X_AXIS_OFFSET = 200;
   private static final int Y_AXIS_OFFSET = 85;
   private static final int PanelHeight = 365;
   private static final int PanelWidth = 1000;

   public DrawPanel() {
      this.setBackground(Color.white);
      this.setPreferredSize(new Dimension(PanelWidth, PanelHeight));
   }

   public void paintComponent(Graphics g) {

      int y = ControlPanel.bk1.getBalance(); // balance
      int x = ControlPanel.bk1.getWeek(); // weeks //
      int prevX, prevY;
      int maxX = ContentPanel.controlPanel.getDuration();
      int maxY = 100000;

      int Xleft = 200;
      int Xright = 900;
      int Ytop = 50;
      int Ybottom = 330;// defining axis

      while (ControlPanel.bk1.getBalance() > maxY) {
         int i = maxY / 4;
         maxY = maxY + i;
      }

      Graphics2D g2 = (Graphics2D) g;
      super.paintComponent(g2);
      g2.setColor(Color.BLUE);

      BasicStroke pen = new BasicStroke(4F);
      g2.setStroke(pen);

      g2.drawLine(Xleft, Ytop, Xleft, Ybottom); // set axis
      g2.drawLine(Xleft, 280, Xright, 280);

      int i = X_AXIS_OFFSET + (X_AXIS_LENGTH / 2);
      int ii = X_AXIS_OFFSET + (X_AXIS_LENGTH / 4);
      int iii = ((X_AXIS_LENGTH / 4)) * 3 + X_AXIS_OFFSET;
      BasicStroke spaces = new BasicStroke(1F);
      g2.setStroke(spaces);
      g2.drawLine(i, 280, i, 300);
      g2.drawLine(ii, 280, ii, 300);
      g2.drawLine(iii, 280, iii, 300);

      g2.setStroke(pen);

      Font f = new Font("Serif", Font.BOLD, 14);
      g2.setFont(f);
      g2.drawString("Account Balance (£)", 35, 200);
      g2.drawString("Elapsed Time (Weeks)", 475, 340);

      g2.setColor(Color.BLACK);
      String maxXDisplay = Integer.toString(maxX);
      String maxYDisplay = Integer.toString(maxY);
      g2.drawString(maxYDisplay, 160, 45);
      g2.drawString(maxXDisplay, 900, 300);

      // retrieve values from your model for the declared variables

      // calculate the coords line on the canvas

      double balance = PanelHeight
            - ((((double) y / maxY) * Y_AXIS_LENGTH) + Y_AXIS_OFFSET);
      double weeks = (((double) x / maxX) * X_AXIS_LENGTH) + X_AXIS_OFFSET;

      int xPos = (int) Math.round(weeks);
      int yPos = (int) Math.round(balance); // changing back to int to be used
                                            // in drawing oval

      g2.setColor(Color.RED);
      g.drawOval(xPos, yPos, 2, 2);

   }

   public void reDraw() {
      repaint();
   }

}

1 Ответ

2 голосов
/ 04 марта 2012

Вы, похоже, пытаетесь построить только одну точку в вашем методе paintComponent:

g.drawOval(xPos, yPos, 2, 2);

Обычно вы будете проходить через цикл for, рисуя все точки в этом методе. Например что-то вроде:

  for (int j = 0; j < maxPointCount; j++) {
     x = someMethodToGetX(j);
     y = someMethodToGetY(j);
     double balance = PanelHeight - ((((double) y / maxY) * 
           Y_AXIS_LENGTH) + Y_AXIS_OFFSET);
     double weeks = (((double) x / maxX) * X_AXIS_LENGTH) + 
           X_AXIS_OFFSET;

     int xPos = (int) Math.round(weeks);
     int yPos = (int) Math.round(balance); 

     g2.setColor(Color.RED);
     g.drawOval(xPos, yPos, 2, 2);
  }

Редактировать 1
По поводу вашего недавнего комментария:

Попробовал это для цикла, и это не имеет значения для программы

Мой код, приведенный выше, определенно не является кодом, который можно вырезать и вставить в вашу программу и который, как ожидается, будет работать, скорее, он будет рассматриваться только как пример концепции. Цикл for будет работать, если он реализован правильно, так как он работал для меня много раз, но ваш не работает, поэтому мы должны исправить вашу реализацию, и для этого нам нужно больше информации:

  • Как вы генерируете свои точки данных?
  • Используете ли вы таймер Swing для имитации сбора данных в режиме реального времени?
  • Вам нужно будет сохранять точки данных по мере их сбора, чтобы ваш paintComponent мог их перебирать. Как вы храните свои данные? Это в ArrayList? Можем ли мы увидеть этот код?
  • Как только мы увидим все это, можем ли мы увидеть код , где вы пытаетесь реализовать цикл for для отрисовки всех точек данных?

Вам нужно будет отредактировать свой вопрос, чтобы показать эту новую информацию. Если вы сделаете это, пожалуйста, сообщите мне, комментируя этот ответ.

Редактировать 2
Это более полный пример того, что я описываю, один с функционирующим циклом for, который рисует все масштабированные точки данных. Конечно, ни один из этого кода не может быть скопирован и вставлен в ваше приложение, но, надеюсь, содержащиеся в нем концепции можно перенести. Пожалуйста, спросите, если что-то выглядит сбивающим с толку:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.event.*;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;

public class TestShowGraph {
   private static final int MAX_POINTS = 30;
   private static final int TIMER_DELAY = 800;

   private static void createAndShowGui() {
      ShowGraph showGraphPanel = new ShowGraph(MAX_POINTS);
      TimerListener timerListener = new TimerListener(MAX_POINTS, showGraphPanel);

      JFrame frame = new JFrame("TestShowGraph");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(showGraphPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);

      new Timer(TIMER_DELAY, timerListener).start();
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }  
}

class TimerListener implements ActionListener {
   private static final double EXP_MULTIPLIER = 0.2;

   // array of points created in constructor to hold data that
   // will eventually be displayed in real time.
   // A Swing Timer will copy a point into the pointsList above. 
   private Point2D[] initPoints;

   private int maxPoints;
   private int count = 0;
   private ShowGraph showGraph;

   public TimerListener(int maxPoints, ShowGraph showGraph) {
      initPoints = new Point2D[maxPoints];
      this.maxPoints = maxPoints;
      this.showGraph = showGraph;

      // create all data points that will eventually be 
      // graphed. This is to simulate real-time data collection
      for (int i = 0; i < initPoints.length; i++) {
         double x = (double) i / initPoints.length;
         double y = 1.0 - Math.exp(-1.0 * i * EXP_MULTIPLIER);        
         initPoints[i] = new Point2D.Double(x, y);
      }
   }

   public void actionPerformed(ActionEvent e) {
      if (count < maxPoints) {
         // simply push data from initPoints into the list that will
         // be used to draw the graph
         showGraph.addPoint(initPoints[count]);
         count++;
      } else {
         // unless we've run out of points. Then simply start over
         count = 0;
         showGraph.clearPointsList();
      }

      // repaint so that the GUI will show the points
      showGraph.repaint();
   }
}

@SuppressWarnings("serial")
class ShowGraph extends JPanel {

   private static final int PREF_W = 800;
   private static final int PREF_H = 600;
   private static final int BORDER_GAP = 50;
   private static final Color AXIS_COLOR = Color.blue;
   private static final Color POINTS_COLOR = Color.red;
   private static final Color BACKGRND_COLOR = Color.white;
   private static final Stroke AXIS_STROKE = new BasicStroke(3f);
   private static final Stroke POINTS_STROKE = new BasicStroke(2f);
   private static final double X_SCALE = PREF_W - 2 * BORDER_GAP;
   private static final double Y_SCALE = PREF_H - 2 * BORDER_GAP;
   private static final int POINT_RADIUS = 3;

   // list that the paintComponent method loops through to
   // draw points
   private List<Point2D> pointsList = new ArrayList<Point2D>();


   public ShowGraph(int maxPoints) {
      setBackground(BACKGRND_COLOR);
   }

   public void addPoint(Point2D point2d) {
      pointsList.add(point2d);
   }

   public void clearPointsList() {
      pointsList.clear();
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g;
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
            RenderingHints.VALUE_ANTIALIAS_ON);
      drawAxises(g2);
      drawPoints(g2);
   }

   private void drawAxises(Graphics g2) {
      // derive a Graphics2D object from the one provided by the 
      // JVM so we can change settings on it without effecting 
      // the Graphics object provided by the JVM
      Graphics2D g2Axises = (Graphics2D) g2.create();
      g2Axises.setStroke(AXIS_STROKE);
      g2Axises.setColor(AXIS_COLOR);
      int x1XAxis = BORDER_GAP;
      int y1XAxis = PREF_H - BORDER_GAP;
      int x2XAxis = PREF_W - BORDER_GAP;
      int y2XAxis = PREF_H - BORDER_GAP;
      g2Axises.drawLine(x1XAxis, y1XAxis, x2XAxis, y2XAxis);
      int x1YAxis = BORDER_GAP;
      int y1YAxis = BORDER_GAP;
      int x2YAxis = BORDER_GAP;
      int y2YAxis = PREF_H - BORDER_GAP;
      g2Axises.drawLine(x1YAxis, y1YAxis, x2YAxis, y2YAxis);
      g2Axises.dispose(); // because we derived this we must dispose it
   }

   private void drawPoints(Graphics2D g2) {
      Graphics2D g2Points = (Graphics2D) g2.create();
      g2Points.setStroke(POINTS_STROKE);
      g2Points.setColor(POINTS_COLOR); 

      for (Point2D p : pointsList) {
         // p points hold data between 0 and 1
         // we must scale our points to fit the display
         // before displaying them
         int pX = (int)(X_SCALE * p.getX()) + BORDER_GAP;
         int pY = PREF_H - (int)(Y_SCALE * p.getY()) - BORDER_GAP;

         // displayed the scaled points
         int radius = POINT_RADIUS;
         g2Points.drawOval(pX - radius, pY - radius, 2 * radius, 2 * radius);
      }
   }

   @Override
   public Dimension getPreferredSize() {
      return new Dimension(PREF_W, PREF_H);
   }

}

Удача.

...