Java Swing绘制动态数据折线图

通过Java Swing可以绘制动态数据折线图。

Java Swing Line Chart

调用下面addData()方法向折线图窗口动态地追加数据,参数t为横轴时间,参数v为纵轴数值,运行效果如上图所示:

Java Swing绘制数据折线图的代码如下:


/* DataWindow.java */
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;

import java.text.DateFormat;
import java.util.Date;

/**
 * Create a new window to graph the sensor readings in.
 *
 * @author Ron Goldman
 */
public class DataWindow extends JFrame {

    private static final int MAX_SAMPLES = 10000;
    private int index = 0;
    private long[] time = new long[MAX_SAMPLES];
    private int[] val = new int[MAX_SAMPLES];
    DateFormat fmt = DateFormat.getDateTimeInstance();

    /** Creates new form DataWindow */
    public DataWindow() {
        initComponents();
    }

    public DataWindow(String ieee) {
        initComponents();
        setTitle(ieee);
    }

    public void addData(long t, int v) {
        time[index] = t;
        val[index++] = v;
        dataTextArea.append(fmt.format(new Date(t)) + "    value = " + v + "\n");
        dataTextArea.setCaretPosition(dataTextArea.getText().length());
        repaint();
    }

    // Graph the sensor values in the dataPanel JPanel
    public void paint(Graphics g) {
        super.paint(g);
        int left = dataPanel.getX() + 10;       // get size of pane
        int top = dataPanel.getY() + 30;
        int right = left + dataPanel.getWidth() - 20;
        int bottom = top + dataPanel.getHeight() - 20;

        int y0 = bottom - 20;                   // leave some room for margins
        int yn = top;
        int x0 = left + 33;
        int xn = right;
        double vscale = (yn - y0) / 120.0;      // light values range from 0 to 800
        double tscale = 1.0 / 2000.0;           // 1 pixel = 2 seconds = 2000 milliseconds

        // draw X axis = time
        g.setColor(Color.BLACK);
        g.drawLine(x0, yn, x0, y0);
        g.drawLine(x0, y0, xn, y0);
        int tickInt = 60 / 2;
        for (int xt = x0 + tickInt; xt < xn; xt += tickInt) {   // tick every 1 minute
            g.drawLine(xt, y0 + 5, xt, y0 - 5);
            int min = (xt - x0) / (60 / 2);
            g.drawString(Integer.toString(min), xt - (min < 10 ? 3 : 7) , y0 + 20);
        }

        // draw Y axis = sensor reading
        g.setColor(Color.BLUE);
        for (int vt = 120; vt > 0; vt -= 20) {         // tick every 200
            int v = y0 + (int)(vt * vscale);
            g.drawLine(x0 - 5, v, x0 + 5, v);
            g.drawString(Integer.toString(vt), x0 - 38 , v + 5);
        }

        // graph sensor values
        int xp = -1;
        int vp = -1;
        for (int i = 0; i < index; i++) {
            int x = x0 + (int)((time[i] - time[0]) * tscale);
            int v = y0 + (int)(val[i] * vscale);
            if (xp > 0) {
                g.drawLine(xp, vp, x, v);
            }
            xp = x;
            vp = v;
        }
    }
    public static void main (String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new DataWindow().setVisible(true);
            }
        });
    }
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // //GEN-BEGIN:initComponents
    private void initComponents() {

        dataPanel = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        dataTextArea = new javax.swing.JTextArea();

        dataPanel.setBackground(new java.awt.Color(255, 255, 255));
        dataPanel.setMinimumSize(new java.awt.Dimension(400, 250));
        dataPanel.setPreferredSize(new java.awt.Dimension(400, 250));
        getContentPane().add(dataPanel, java.awt.BorderLayout.CENTER);

        jScrollPane1.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        jScrollPane1.setMinimumSize(new java.awt.Dimension(400, 100));
        jScrollPane1.setPreferredSize(new java.awt.Dimension(400, 100));

        dataTextArea.setColumns(20);
        dataTextArea.setEditable(false);
        dataTextArea.setRows(4);
        jScrollPane1.setViewportView(dataTextArea);

        getContentPane().add(jScrollPane1, java.awt.BorderLayout.SOUTH);

        pack();
    }// //GEN-END:initComponents

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel dataPanel;
    private javax.swing.JTextArea dataTextArea;
    private javax.swing.JScrollPane jScrollPane1;
    // End of variables declaration//GEN-END:variables

}

本文链接:http://bookshadow.com/weblog/2014/05/16/java-swing-line-chart/
请尊重作者的劳动成果,转载请注明出处!书影博客保留对文章的所有权利。

如果您喜欢这篇博文,欢迎您捐赠书影博客: ,查看支付宝二维码

Pingbacks已关闭。

评论
  1. kacel kacel 发布于 2014年12月21日 21:48 #

    调用addData( )那个函数,要怎么调用叻?

  2. 在线疯狂 在线疯狂 发布于 2014年12月24日 16:41 #

    传入两个参数t和v:分别代表数据时间和数值

  3. kacel kacel 发布于 2014年12月24日 19:47 #

    我想每秒从文档里或者数据库里每秒读取一个数据出来,是应该把这个函数写在主函数里面么?话说,你示例的那个图的数据的读取部分的程序可不可以发我一份叻??有没有私信之类的功能><

  4. 在线疯狂 在线疯狂 发布于 2014年12月24日 20:20 #

    可以用线程实现异步地追加数据。这个程序的历史过于久远。。。目前只能找到这个代码片段了>_<

  5. 在线疯狂 在线疯狂 发布于 2014年12月24日 20:54 #

    把代码里的main方法替换成下面的片段就可以看到随机数据构造的折线图了。
    private static final DataWindow dw = new DataWindow();
    public static void main (String args[]) {
    java.awt.EventQueue.invokeLater(new Runnable() {
    public void run() {
    dw.setVisible(true);
    }
    });
    Thread thread = new Thread() {
    public void run() {
    while (true) {
    long t = System.currentTimeMillis();
    int v = new Random().nextInt(50);
    dw.addData(t, v);
    dw.repaint();
    try {
    Thread.sleep(2000L);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    }
    };
    thread.run();
    }

  6. kacel kacel 发布于 2014年12月24日 21:26 #

    哇塞,,好感动,。非常感谢。

  7. 有宇颜 有宇颜 发布于 2016年4月7日 18:32 #

    可以一次画多条折线吗?

  8. 魏建强 魏建强 发布于 2016年7月14日 11:07 #

    在main方法中调用addDate()方法吗?

张贴您的评论