gpt4 book ai didi

java - JPanel添加但不显示 "in time"

转载 作者:搜寻专家 更新时间:2023-11-01 01:35:46 25 4
gpt4 key购买 nike

我有一个 JFrame,它根据您单击的 MenuItem 显示 JPanel。它有效,但现在我需要在将 JPanel 添加到框架并显示它后调用一个方法(因为我在该面板内使用 JFreeChart,我必须调用 chartPanel.repaint() 当 JPanel 可见时):

this.getContentPane().add( myjpanel, BorderLayout.CENTER ); //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,"You should see myjpanel now");
chartPanel.repaint()
}

现在它工作了,我在警报后面看到 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 );    }}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();    }}

看看使用和不使用 JOptionPane 会发生什么。

最佳答案

An explanation of why is this happening would be great.

您可能会从下面的变体中获得一些见解。注意

  • Swing GUI 对象应该event dispatch thread 上构造和操作(EDT) 原因建议here .

  • EDT 继续处理事件,如示例所示,即使用户交互仅限于模式对话框也是如此。

  • 调用 repaint()使用 ChartPanel不需要 .

  • 首选 CardLayout JTabbedPane 优于手动容器操作。

  • 而不是调用 setPreferredSize() , 覆盖 getPreferredSize() ,正如所讨论的here .

附录:您删除了显示问题的两行......

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

EventQueue.invokeLater(new Runnable() {

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

更好的方案是访问 ChartRenderingInfo在您知道数据有效的监听器中,即由 ChartPanel 实现的监听器.

image

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!");
}
}
}

附录:一个额外的迭代来说明 ChartMouseListener并清理一些 Unresolved 问题。

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;
}
}
}

关于java - JPanel添加但不显示 "in time",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14874967/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com