import java.awt.BorderLayout;导入 java.awt.Dimension;导入 java.awt.EventQueue;导入 java.awt.event.ActionEvent;导入 java.awt.event.ActionListener;导入 java.util.Date;导入 java.util.Random;导入 javax.swing.JButton;导入 javax.swing.JFrame;导入 javax.swing.JLabel;导入 javax.swing.JOptionPane;导入 javax.swing.JPanel;导入 javax.swing.Timer;导入 javax.swing.border.EmptyBorder;导入 org.jfree.chart.ChartPanel;导入 org.jfree.chart.JFreeChart;导入 org.jfree.chart.axis.DateAxis;导入 org.jfree.chart.axis.NumberAxis;导入 org.jfree.chart.plot.CombinedDomainXYPlot;导入 org.jfree.chart.plot.PlotOrientation;导入 org.jfree.chart.plot.PlotRenderingInfo;导入 org.jfree.chart.plot.XYPlot;导入 org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;导入 org.jfree.data.time.Day;导入 org.jfree.data.time.TimeSeries;导入 org.jfree.data.time.TimeSeriesCollection;导入 org.jfree.data.xy.XY 数据集;/*** @see https://stackoverflow.com/a/14894894/230513*/公共类测试扩展 JFrame {私人 JPanel 面板;公共静态无效主(字符串 [] args){EventQueue.invokeLater(new Runnable() {@覆盖公共无效运行(){测试框架 = new Test();框架.pack();frame.setLocationRelativeTo(null);frame.setVisible(true);}});}公共测试(){setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);最后的 MyJPanel myPanel = new MyJPanel();面板 = 新 JPanel() {@覆盖公共维度 getPreferredSize() {返回 myPanel.getPreferredSize();}};panel.setBorder(new EmptyBorder(5, 5, 5, 5));panel.setLayout(new BorderLayout());添加(面板);myPanel.start();JButton clickme = new JButton("点击我");clickme.addActionListener(new ActionListener() {@覆盖公共无效动作执行(ActionEvent arg0){panel.removeAll();panel.add(myPanel, BorderLayout.CENTER);证实();EventQueue.invokeLater(new Runnable() {@覆盖公共无效运行(){myPanel.methodCalledOnceDisplayed();}});}});panel.add(clickme, BorderLayout.NORTH);JPanel 示例 = new JPanel();example.add(new JLabel("Example JPanel"));panel.add(例如,BorderLayout.CENTER);}私有静态类 MyJPanel 扩展 JPanel {私有静态最终随机 r = 新随机();私人图表面板图表面板;私人 JFreeChart 图表;私人 XYPlot subplotTop;私人 XYPlot subplotBottom;私有的 CombinedDomainXYPlot 图;私人定时器定时器;现在私人日 = 新日(新日期());公共 MyJPanel() {this.add(new JLabel("图表面板"));createCombinedChart();chartPanel = new ChartPanel(chart);this.add(chartPanel);计时器 = 新计时器(1000,新 ActionListener(){@覆盖public void actionPerformed(ActionEvent e) {更新(subplotTop);更新(subplotBottom);}});定时器开始();}公共无效开始(){定时器开始();}私人无效更新(XYPlot 图){TimeSeriesCollection t = (TimeSeriesCollection) plot.getDataset();for (int i = 0; i < t.getSeriesCount(); i++) {时间序列 s = t.getSeries(i);s.add(现在,Math.abs(r.nextGaussian()));now = (Day) now.next();}}私有无效 createCombinedChart() {plot = new CombinedDomainXYPlot();plot.setGap(30);创建子图();plot.add(subplotTop, 4);plot.add(subplotBottom, 1);plot.setOrientation(PlotOrientation.VERTICAL);chart = new JFreeChart("Title",JFreeChart.DEFAULT_TITLE_FONT,情节,真);plot.setDomainAxis(new DateAxis("Domain"));}私人无效createSubplots(){subplotTop = 新 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"));}私人 XYDataset 空数据集(字符串标题){TimeSeriesCollection tsc = new TimeSeriesCollection();TimeSeries ts = new TimeSeries(title);tsc.addSeries(ts);返回 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!");}}}附录:一个额外的迭代来说明 ChartMouseListener 并清理一些未解决的问题.import java.awt.BorderLayout;导入 java.awt.EventQueue;导入 java.awt.event.ActionEvent;导入 java.awt.event.ActionListener;导入 java.util.Date;导入 java.util.Random;导入 javax.swing.JFrame;导入 javax.swing.JPanel;导入 javax.swing.Timer;导入 org.jfree.chart.ChartMouseEvent;导入 org.jfree.chart.ChartMouseListener;导入 org.jfree.chart.ChartPanel;导入 org.jfree.chart.JFreeChart;导入 org.jfree.chart.axis.DateAxis;导入 org.jfree.chart.axis.NumberAxis;导入 org.jfree.chart.entity.ChartEntity;导入 org.jfree.chart.plot.CombinedDomainXYPlot;导入 org.jfree.chart.plot.PlotOrientation;导入 org.jfree.chart.plot.XYPlot;导入 org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;导入 org.jfree.data.time.Day;导入 org.jfree.data.time.TimeSeries;导入 org.jfree.data.time.TimeSeriesCollection;导入 org.jfree.data.xy.XY 数据集;/*** @see https://stackoverflow.com/a/14894894/230513*/公共类测试{公共静态无效主(字符串 [] args){EventQueue.invokeLater(new Runnable() {@覆盖公共无效运行(){测试 t = 新测试();}});}公共测试(){JFrame f = new JFrame();f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);最后的 MyJPanel myPanel = new MyJPanel();f.add(myPanel, BorderLayout.CENTER);f.pack();f.setLocationRelativeTo(null);f.setVisible(true);myPanel.start();}私有静态类 MyJPanel 扩展 JPanel {私有静态最终随机 r = 新随机();私人图表面板图表面板;私人 JFreeChart 图表;私人 XYPlot subplotTop;私人 XYPlot subplotBottom;私有的 CombinedDomainXYPlot 图;私人定时器定时器;现在私人日 = 新日(新日期());公共 MyJPanel() {createCombinedChart();chartPanel = new ChartPanel(chart);this.add(chartPanel);计时器 = 新计时器(1000,新 ActionListener(){@覆盖public void actionPerformed(ActionEvent e) {更新(subplotTop);更新(subplotBottom);now = (Day) now.next();}});chartPanel.addChartMouseListener(new ChartMouseListener() {@覆盖public void chartMouseClicked(ChartMouseEvent e) {最终 ChartEntity entity = e.getEntity();System.out.println(entity + " " + entity.getArea());}@覆盖public void chartMouseMoved(ChartMouseEvent e) {}});}公共无效开始(){定时器开始();}私人无效更新(XYPlot 图){TimeSeriesCollection t = (TimeSeriesCollection) plot.getDataset();for (int i = 0; i < t.getSeriesCount(); i++) {时间序列 s = t.getSeries(i);s.add(现在,Math.abs(r.nextGaussian()));}}私有无效 createCombinedChart() {plot = new CombinedDomainXYPlot();创建子图();plot.add(subplotTop, 4);plot.add(subplotBottom, 1);plot.setOrientation(PlotOrientation.VERTICAL);chart = new JFreeChart("Title",JFreeChart.DEFAULT_TITLE_FONT,情节,真);plot.setDomainAxis(new DateAxis("Domain"));}私人无效createSubplots(){subplotTop = 新 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"));}私人 XYDataset 空数据集(字符串标题){TimeSeriesCollection tsc = new TimeSeriesCollection();TimeSeries ts = new TimeSeries(title);tsc.addSeries(ts);返回 tsc;}}}I have a JFrame that displays JPanels depending on the MenuItem you click. It works, but now I need to call a method once a JPanel is added to the frame and it is being shown (because I'm using JFreeChart inside that panel and I have to call chartPanel.repaint() when the JPanel is visible):this.getContentPane().add( myjpanel, BorderLayout.CENTER ); //this = JFramethis.validate();myjpanel.methodCalledOnceDisplayed();Does it seem ok? Is myjpanel being shown really? It seems it is not:public void methodCalledOnceDisplayed() { chartPanel.repaint()}This is not working (chartPanel.getChartRenderingInfo().getPlotInfo().getSubplotInfo(0) is throwing IndexOutOfBoundsException). That means that the JPanel was not visible when repaint was called, I've tested the following:public void methodCalledOnceDisplayed() { JOptionPane.showMessageDialog(null,"You should see myjpanel now"); chartPanel.repaint()}Now it works, I see myjpanel behind the alert, just as expected, chartPanel is repainted and no Exception occurs.EDIT: SSCCE (jfreechart and jcommon needed: http://www.jfree.org/jfreechart/download.html)import java.awt.BorderLayout;import java.awt.EventQueue;import java.awt.Font;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JOptionPane;import javax.swing.JPanel;import javax.swing.border.EmptyBorder;import org.jfree.chart.ChartMouseEvent;import org.jfree.chart.ChartMouseListener;import org.jfree.chart.JFreeChart;import org.jfree.chart.plot.CombinedDomainXYPlot;import org.jfree.chart.plot.PlotOrientation;import org.jfree.chart.plot.XYPlot;import org.jfree.chart.ChartPanel;import org.jfree.data.time.TimeSeries;import org.jfree.data.time.TimeSeriesCollection;import org.jfree.data.xy.XYDataset;import java.awt.event.ActionListener;import java.awt.event.ActionEvent;public class Window extends JFrame { private JPanel contentPane; public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { Window frame = new Window(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } public Window() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 700, 500); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); contentPane.setLayout(new BorderLayout(0, 0)); setContentPane(contentPane); JButton clickme = new JButton("Click me"); clickme.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { contentPane.removeAll(); MyJPanel mypanel = new MyJPanel(); contentPane.add( mypanel, BorderLayout.CENTER ); validate(); mypanel.methodCalledOnceDisplayed(); } }); contentPane.add( clickme, BorderLayout.NORTH ); JPanel example = new JPanel(); example.add( new JLabel("Example JPanel") ); contentPane.add( example, BorderLayout.CENTER ); }}class MyJPanel extends JPanel implements ChartMouseListener { private ChartPanel chartPanel; private JFreeChart chart; private XYPlot subplotTop; private XYPlot subplotBottom; private CombinedDomainXYPlot plot; public MyJPanel() { this.add( new JLabel("This JPanel contains the chart") ); createCombinedChart(); chartPanel = new ChartPanel(chart); chartPanel.addChartMouseListener(this); this.add( chartPanel ); } 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", new Font("Arial", Font.BOLD,20), plot, true); } private void createSubplots() { subplotTop = new XYPlot(); subplotBottom = new XYPlot(); subplotTop.setDataset(emptyDataset("Empty 1")); subplotBottom.setDataset(emptyDataset("Empty 2")); } private XYDataset emptyDataset( String title ) { TimeSeries ts = new TimeSeries(title); TimeSeriesCollection tsc = new TimeSeriesCollection(); tsc.addSeries(ts); return tsc; } @Override public void chartMouseMoved(ChartMouseEvent e) { System.out.println("Mouse moved!"); } @Override public void chartMouseClicked(ChartMouseEvent arg0) {} public void methodCalledOnceDisplayed() { JOptionPane.showMessageDialog(null,"Magic!"); //try to comment this line and see the console chartPanel.repaint(); //now we can get chart areas this.chartPanel.getChartRenderingInfo().getPlotInfo().getSubplotInfo(0).getDataArea(); this.chartPanel.getChartRenderingInfo().getPlotInfo().getSubplotInfo(1).getDataArea(); }}See what happens with and without the JOptionPane. 解决方案 You may get some insight from the variation below. NoteSwing GUI objects should be constructed and manipulated only on the event dispatch thread (EDT) for the reason suggested here.The EDT continues to process events, as shown in the example, even while user interaction is limited to the modal dialog.Invoking repaint() should not be required when using ChartPanel.Prefer CardLayout or JTabbedPane over manual container manipulation.Rather than invoking setPreferredSize(), override getPreferredSize(), as discussed here.Addendum: You have removed the two lines … that are showing the problem.ChartRenderingInfo is dynamic data that doesn't exist until the chart has been rendered. The modal dialog handles events while the chart is updated in the background; without it, you can schedule your method by wrapping it in a Runnable suitable for invokeLater():EventQueue.invokeLater(new Runnable() { @Override public void run() { myPanel.methodCalledOnceDisplayed(); }});A better scheme is to access the ChartRenderingInfo in listeners where you know the data is valid, i.e. listeners implemented by 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;/*** @see https://stackoverflow.com/a/14894894/230513*/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 ChartMouseListener and 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;/** * @see https://stackoverflow.com/a/14894894/230513 */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; } }} 这篇关于JPanel已添加但未“及时"显示的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云! 05-30 20:26