为什么会发生这种情况的解释会很好。
您可以从以下变体中获得一些见解。注意
出于此处建议的原因,应仅在事件分发线程(EDT)上构造和操作Swing GUI对象。
如示例中所示,即使用户交互仅限于模式对话框,EDT仍继续处理事件。
调用
repaint()应该不使用时可能需要
ChartPanel。
喜欢
CardLayout或
JTabbedPane比手动容器操纵。
而不是调用
setPreferredSize(),覆盖
getPreferredSize(),为讨论在这里。
附录:您删除了显示问题的两行……。
ChartRenderingInfo是动态数据,在呈现图表之前不存在。模式图对话框在后台更新图表时处理事件。没有它,您可以通过将其包装在
Runnable合适的方法中来安排方法
invokeLater():
EventQueue.invokeLater(new Runnable() { @Override public void run() { myPanel.methodCalledonceDisplayed(); }});更好的方案是
ChartRenderingInfo在您
知道数据有效的地方访问in侦听器,即由实现的侦听器ChartPanel。
import java.awt.BorderLayout;import java.awt.Dimension;import java.awt.EventQueue;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.util.Date;import java.util.Random;import javax.swing.JButton;import javax.swing.Jframe;import javax.swing.JLabel;import javax.swing.JOptionPane;import javax.swing.JPanel;import javax.swing.Timer;import javax.swing.border.EmptyBorder;import org.jfree.chart.ChartPanel;import org.jfree.chart.JFreeChart;import org.jfree.chart.axis.DateAxis;import org.jfree.chart.axis.NumberAxis;import org.jfree.chart.plot.CombinedDomainXYPlot;import org.jfree.chart.plot.PlotOrientation;import org.jfree.chart.plot.PlotRenderingInfo;import org.jfree.chart.plot.XYPlot;import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;import org.jfree.data.time.Day;import org.jfree.data.time.TimeSeries;import org.jfree.data.time.TimeSeriesCollection;import org.jfree.data.xy.XYDataset;public class Test extends Jframe { private JPanel panel; public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { Test frame = new Test(); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public Test() { setDefaultCloseOperation(Jframe.EXIT_ON_CLOSE); final MyJPanel myPanel = new MyJPanel(); panel = new JPanel() { @Override public Dimension getPreferredSize() { return myPanel.getPreferredSize(); } }; panel.setBorder(new EmptyBorder(5, 5, 5, 5)); panel.setLayout(new BorderLayout()); add(panel); myPanel.start(); JButton clickme = new JButton("Click me"); clickme.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { panel.removeAll(); panel.add(myPanel, BorderLayout.CENTER); validate(); EventQueue.invokeLater(new Runnable() { @Override public void run() { myPanel.methodCalledonceDisplayed(); } }); } }); panel.add(clickme, BorderLayout.NORTH); JPanel example = new JPanel(); example.add(new JLabel("Example JPanel")); panel.add(example, BorderLayout.CENTER); } private static class MyJPanel extends JPanel { private static final Random r = new Random(); private ChartPanel chartPanel; private JFreeChart chart; private XYPlot subplotTop; private XYPlot subplotBottom; private CombinedDomainXYPlot plot; private Timer timer; private Day now = new Day(new Date()); public MyJPanel() { this.add(new JLabel("Chart panel")); createCombinedChart(); chartPanel = new ChartPanel(chart); this.add(chartPanel); timer = new Timer(1000, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { update(subplotTop); update(subplotBottom); } }); timer.start(); } public void start() { timer.start(); } private void update(XYPlot plot) { TimeSeriesCollection t = (TimeSeriesCollection) plot.getDataset(); for (int i = 0; i < t.getSeriesCount(); i++) { TimeSeries s = t.getSeries(i); s.add(now, Math.abs(r.nextGaussian())); now = (Day) now.next(); } } private void createCombinedChart() { plot = new CombinedDomainXYPlot(); plot.setGap(30); createSubplots(); plot.add(subplotTop, 4); plot.add(subplotBottom, 1); plot.setOrientation(PlotOrientation.VERTICAL); chart = new JFreeChart("Title", JFreeChart.DEFAULT_TITLE_FONT, plot, true); plot.setDomainAxis(new DateAxis("Domain")); } private void createSubplots() { subplotTop = new XYPlot(); subplotBottom = new XYPlot(); subplotTop.setDataset(emptyDataset("Set 1")); subplotTop.setRenderer(new XYLineAndShapeRenderer()); subplotTop.setRangeAxis(new NumberAxis("Range")); subplotBottom.setDataset(emptyDataset("Set 2")); subplotBottom.setRenderer(new XYLineAndShapeRenderer()); subplotBottom.setRangeAxis(new NumberAxis("Range")); } private XYDataset emptyDataset(String title) { TimeSeriesCollection tsc = new TimeSeriesCollection(); TimeSeries ts = new TimeSeries(title); tsc.addSeries(ts); return tsc; } public void methodCalledonceDisplayed() { PlotRenderingInfo plotInfo = this.chartPanel.getChartRenderingInfo().getPlotInfo(); for (int i = 0; i < plotInfo.getSubplotCount(); i++) { System.out.println(plotInfo.getSubplotInfo(i).getDataArea()); } JOptionPane.showMessageDialog(null, "Magic!"); } }}Addendum: One additional iteration to illustrate
ChartMouseListenerand
clean up a few loose ends.
import java.awt.BorderLayout;import java.awt.EventQueue;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.util.Date;import java.util.Random;import javax.swing.Jframe;import javax.swing.JPanel;import javax.swing.Timer;import org.jfree.chart.ChartMouseEvent;import org.jfree.chart.ChartMouseListener;import org.jfree.chart.ChartPanel;import org.jfree.chart.JFreeChart;import org.jfree.chart.axis.DateAxis;import org.jfree.chart.axis.NumberAxis;import org.jfree.chart.entity.ChartEntity;import org.jfree.chart.plot.CombinedDomainXYPlot;import org.jfree.chart.plot.PlotOrientation;import org.jfree.chart.plot.XYPlot;import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;import org.jfree.data.time.Day;import org.jfree.data.time.TimeSeries;import org.jfree.data.time.TimeSeriesCollection;import org.jfree.data.xy.XYDataset;public class Test { public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { Test t = new Test(); } }); } public Test() { Jframe f = new Jframe(); f.setDefaultCloseOperation(Jframe.EXIT_ON_CLOSE); final MyJPanel myPanel = new MyJPanel(); f.add(myPanel, BorderLayout.CENTER); f.pack(); f.setLocationRelativeTo(null); f.setVisible(true); myPanel.start(); } private static class MyJPanel extends JPanel { private static final Random r = new Random(); private ChartPanel chartPanel; private JFreeChart chart; private XYPlot subplotTop; private XYPlot subplotBottom; private CombinedDomainXYPlot plot; private Timer timer; private Day now = new Day(new Date()); public MyJPanel() { createCombinedChart(); chartPanel = new ChartPanel(chart); this.add(chartPanel); timer = new Timer(1000, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { update(subplotTop); update(subplotBottom); now = (Day) now.next(); } }); chartPanel.addChartMouseListener(new ChartMouseListener() { @Override public void chartMouseClicked(ChartMouseEvent e) { final ChartEntity entity = e.getEntity(); System.out.println(entity + " " + entity.getArea()); } @Override public void chartMouseMoved(ChartMouseEvent e) { } }); } public void start() { timer.start(); } private void update(XYPlot plot) { TimeSeriesCollection t = (TimeSeriesCollection) plot.getDataset(); for (int i = 0; i < t.getSeriesCount(); i++) { TimeSeries s = t.getSeries(i); s.add(now, Math.abs(r.nextGaussian())); } } private void createCombinedChart() { plot = new CombinedDomainXYPlot(); createSubplots(); plot.add(subplotTop, 4); plot.add(subplotBottom, 1); plot.setOrientation(PlotOrientation.VERTICAL); chart = new JFreeChart("Title", JFreeChart.DEFAULT_TITLE_FONT, plot, true); plot.setDomainAxis(new DateAxis("Domain")); } private void createSubplots() { subplotTop = new XYPlot(); subplotBottom = new XYPlot(); subplotTop.setDataset(emptyDataset("Set 1")); subplotTop.setRenderer(new XYLineAndShapeRenderer()); subplotTop.setRangeAxis(new NumberAxis("Range")); subplotBottom.setDataset(emptyDataset("Set 2")); subplotBottom.setRenderer(new XYLineAndShapeRenderer()); subplotBottom.setRangeAxis(new NumberAxis("Range")); } private XYDataset emptyDataset(String title) { TimeSeriesCollection tsc = new TimeSeriesCollection(); TimeSeries ts = new TimeSeries(title); tsc.addSeries(ts); return tsc; } }}


