通过Java Swing可以绘制动态数据折线图。
调用下面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/
请尊重作者的劳动成果,转载请注明出处!书影博客保留对文章的所有权利。
kacel 发布于 2014年12月21日 21:48 #
调用addData( )那个函数,要怎么调用叻?
在线疯狂 发布于 2014年12月24日 16:41 #
传入两个参数t和v:分别代表数据时间和数值
kacel 发布于 2014年12月24日 19:47 #
我想每秒从文档里或者数据库里每秒读取一个数据出来,是应该把这个函数写在主函数里面么?话说,你示例的那个图的数据的读取部分的程序可不可以发我一份叻??有没有私信之类的功能><
在线疯狂 发布于 2014年12月24日 20:20 #
可以用线程实现异步地追加数据。这个程序的历史过于久远。。。目前只能找到这个代码片段了>_<
在线疯狂 发布于 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();
}
kacel 发布于 2014年12月24日 21:26 #
哇塞,,好感动,。非常感谢。
有宇颜 发布于 2016年4月7日 18:32 #
可以一次画多条折线吗?
魏建强 发布于 2016年7月14日 11:07 #
在main方法中调用addDate()方法吗?