JPanel被添加但未被“按时”显示。 [英] JPanel added but not displayed "in time"

查看:685
本文介绍了JPanel被添加但未被“按时”显示。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个JFrame显示JPanels根据你点击的MenuItem。它的工作原理,但现在我需要调用一个方法一旦JPanel添加到框架和它被显示(因为我在该面板中使用JFreeChart,我必须调用 chartPanel.repaint() 当JPanel可见时):

  this.getContentPane()add(myjpanel,BorderLayout。中央 ); // this = JFrame 
this.validate();
myjpanel.methodCalledOnceDisplayed();

看起来确定吗?是否显示 myjpanel ?似乎不是:

  public void methodCalledOnceDisplayed(){
chartPanel.repaint()
}

这不起作用( chartPanel.getChartRenderingInfo()。getPlotInfo()。 getSubplotInfo(0)正在抛出IndexOutOfBoundsException)。这意味着调用重绘时,JPanel不可见,我测试了以下内容:

  public void methodCalledOnceDisplayed 
JOptionPane.showMessageDialog(null,你应该看到myjpanel现在);
chartPanel.repaint()
}

code> myjpanel 后面的警报,正如预期,chartPanel被重画,没有发生异常。



编辑:SSCCE(需要jfreechart和jcommon: 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);
}

}

类MyJPanel extends JPanel实现ChartMouseListener {
private ChartPanel chartPanel;
private JFreeChart图;
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 !); //尝试评论这一行,看到控制台
chartPanel.repaint();
//现在我们可以得到图表区域
this.chartPanel.getChartRenderingInfo()。getPlotInfo()。getSubplotInfo(0).getDataArea();
this.chartPanel.getChartRenderingInfo()。getPlotInfo()。getSubplotInfo(1).getDataArea();
}
}

查看在使用和不使用JOptionPane的情况下会发生什么。


b
$ b

您可以从下面的变化中得到一些见解。注




  • Swing GUI对象只能在事件派发线程(EDT)因为建议的原因在这里


  • EDT继续处理事件,如示例所示,甚至


  • 调用 repaint()


  • 首选 CardLayout JTabbedPane 超过手动容器处理。


  • > setPreferredSize(),覆盖 getPreferredSize(),如此处




补充:该问题。



ChartRenderingInfo 是在图表呈现之前不存在的动态数据。模式对话框处理事件,同时在后台更新图表;没有它,你可以通过将它包装在适用于 invokeLater() Runnable 中来安排你的方法:

  EventQueue.invokeLater(new Runnable(){

@Override
public void run(){
myPanel.methodCalledOnceDisplayed();
}
});

一个更好的方案是访问 ChartRenderingInfo 在您知道数据有效的侦听器中,即 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 http://stackoverflow.com/a/14894894/230513
* /
public class Test extends JFrame {

私人JPanel面板;

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图;
private XYPlot subplotTop;
private XYPlot subplotBottom;
private CombinedDomainXYPlot plot;
private timer timer;
private现在= 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 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!);
}
}
}

补充:说明 ChartMouseListener 并清理一些松散的结束。

  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 http://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图;
private XYPlot subplotTop;
private XYPlot subplotBottom;
private CombinedDomainXYPlot plot;
private timer timer;
private现在= 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();
}

私有无效更新(XYPlot绘图){
TimeSeriesCollection t =(TimeSeriesCollection)plot.getDataset();
for(int i = 0; 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;
}
}
}


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 = JFrame
this.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.

解决方案

An explanation of why is this happening would be great.

You may get some insight from the variation below. Note

  • Swing 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 http://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 http://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被添加但未被“按时”显示。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆