我目前正在开发一个程序,其中某些随时间演变的数值变量会在每次迭代时显示其值。这很好用,但现在我想绘制一张图表,显示它们随时间的演变。 所以,我查看了一个用于在Swing中绘制图形的代码示例。我的最终代码如下所示:
public class Populus3 extends JPanel
{
public static void main(String[] args) throws IOException {
final Populus3 pop = new Populus3();
JFrame f = new JFrame(); //where I want to plot the graph
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new GraphingData());
f.setSize(400,400);
f.setLocation(200,200);
f.setVisible(true);
frame = new JFrame("Animation Frame"); //where I'm running animation for another element of the program
frame.add(pop, BorderLayout.CENTER);
frame.setSize(graphSize, graphSize);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//insert all sort of things
}
public void paint(Graphics g)
{
super.paint(g);
paintCell(g, 1);
Toolkit.getDefaultToolkit().sync(); // necessary for linux users to draw and animate image correctly
g.dispose();
}
public void actionPerformed(ActionEvent e) {
repaint();
}
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
for(int i = 0; i < particleType.length; i++)
paintCell(g, i); //a method that draws a small circle for the animation panel
}
public static class GraphingData extends JPanel {
int[] data = {
21, 14, 18, 03, 86, 88, 74, 87, 54, 77,
61, 55, 48, 60, 49, 36, 38, 27, 20, 18
};
final int PAD = 20;
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();
// Draw ordinate.
g2.draw(new Line2D.Double(PAD, PAD, PAD, h-PAD));
// Draw abcissa.
g2.draw(new Line2D.Double(PAD, h-PAD, w-PAD, h-PAD));
double xInc = (double)(w - 2*PAD)/(data.length-1);
double scale = (double)(h - 2*PAD)/getMax();
// Mark data points.
g2.setPaint(Color.red);
for(int i = 0; i < data.length; i++) {
double x = PAD + i*xInc;
double y = h - PAD - scale*data[i];
g2.fill(new Ellipse2D.Double(x-2, y-2, 4, 4));
}
}
private int getMax() {
int max = -Integer.MAX_VALUE;
for(int i = 0; i < data.length; i++) {
if(data[i] > max)
max = data[i];
}
return max;
}
}
}
现在,动画面板工作得很好。另一方面,图形面板......当我运行程序时,它会显示一堆红点,没有连接它们的线条。我做错了什么?
答案 0 :(得分:6)
除了@ Hovercraft的有用建议外,还要考虑其他方法:
GeneralPath
中可能根据需要呈现example的点数。
drawLine()
重复调用{{1}}来连接点,概述here。
JFreeChart
。答案 1 :(得分:5)
您的代码让我感到困惑:
paintCell(...)
。Toolkit.getDefaultToolkit().sync();
的Swing应用程序。你有这个需求的参考吗?考虑更多地隔离您的问题并发布sscce,这是一个我们可以编译,运行,修改和更正的最小测试程序,它向我们展示了您的问题,但是没有与问题或要求无关的额外代码用于演示。
答案 2 :(得分:0)
以下代码演示了使用XChart的实时Java图表,其中随着时间的推移数据随着时间的推移而更新。创建实时图表就像通过updateXYSeries
实例为一个或多个系列对象调用XYChart
并触发包含图表的JPanel
的重绘一样简单。这适用于所有图表类型,包括XYChart
,CategoryChart
,BubbleChart
和PieChart
,其示例源代码可在此处找到:https://github.com/timmolter/XChart/tree/develop/xchart-demo/src/main/java/org/knowm/xchart/demo/charts/realtime。示例演示了使用SwingWrapper
repaintChart()
方法以及XChartPanel
revalidate()
和repaint()
。免责声明,我是XChart库的主要开发人员。
public class SimpleRealTime {
public static void main(String[] args) throws Exception {
double phase = 0;
double[][] initdata = getSineData(phase);
// Create Chart
final XYChart chart = QuickChart.getChart("Simple XChart Real-time Demo", "Radians", "Sine", "sine", initdata[0], initdata[1]);
// Show it
final SwingWrapper<XYChart> sw = new SwingWrapper<XYChart>(chart);
sw.displayChart();
while (true) {
phase += 2 * Math.PI * 2 / 20.0;
Thread.sleep(100);
final double[][] data = getSineData(phase);
chart.updateXYSeries("sine", data[0], data[1], null);
sw.repaintChart();
}
}
private static double[][] getSineData(double phase) {
double[] xData = new double[100];
double[] yData = new double[100];
for (int i = 0; i < xData.length; i++) {
double radians = phase + (2 * Math.PI / xData.length * i);
xData[i] = radians;
yData[i] = Math.sin(radians);
}
return new double[][] { xData, yData };
}
}