在组件绘制时摆动对话框

在组件绘制时摆动对话框

本文介绍了如何创建“请稍候"?在组件绘制时摆动对话框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于Swing来说还是一个相对较新的事物,但是经过几个小时的搜索,我无法在网上找到答案,因此这篇文章(对不起,如果已经回答了,我却忽略了它).

Still relatively new to Swing but after a couple of hours of search, I couldn't find the answer online, hence this post (sorry if already answered and I overlooked it).

我在Swing应用程序中使用JFreeChart.一些图表相对较重(180k数据点),并且JFreeChart的ChartPanel大约需要6秒钟才能完成其第一个paintComponent().

I'm using JFreeChart in a Swing application. Some charts are relatively heavy (180k data points) and the JFreeChart's ChartPanel needs ~6 seconds to do its first paintComponent().

因此,我想在组件绘画时在对话框中显示请稍候"消息(无需显示SwingWorker的进度).我试图重写paintComponent方法,但不幸的是,该消息从未出现在屏幕上(我想线程直接进入了绘制图表的时间,而没有花时间绘制对话框).

Hence I would like to show a "Please wait" message in a dialog while the component paints (no need to show progress with a SwingWorker). I tried to override the paintComponent method but unfortunately the message never appears on screen (I guess the thread directly goes into painting the chart, without taking the time to paint the dialog).

我的代码如下:

public class CustomizedChartPanel extends ChartPanel{

private static final long serialVersionUID = 1L;
private JDialog dialog = null;
boolean isPainted = false;

public CustomizedChartPanel(JFreeChart chart) { super(chart); }

@Override
public void paintComponent(Graphics g) {
    //At first paint (which can be lengthy for large charts), show "please wait" message
    if (! isPainted){
        dialog = new JDialog();
        dialog.setUndecorated(true);
        JPanel panel = new JPanel();
        panel.add(new JLabel("Please wait"));
        dialog.add(panel);
        dialog.pack();
        GuiHelper.centerDialog(dialog); //Custom code to center the dialog on the screen
        dialog.setVisible(true);
        dialog.repaint();
    }

    super.paintComponent(g);

    if (! isPainted){
        isPainted = true;
        dialog.dispose();
            super.repaint();
        }
}
}

非常感谢您提供有关如何解决此问题/最佳做法的指导!

Any pointer on how to solve this / best practices would be very much appreciated!

谢谢,托马斯

更新:

感谢您的提示和&辩论:非常有帮助.

Thanks for the hints & debate: very helpful.

我开始使用invokeLater()来实现建议的解决方案,因为我担心JLayer解决方案无法运行,因为它也在EDT上运行.

I started implementing the suggested solution with the invokeLater() as I'm fearing that the JLayer solution won't work since it's also running on the EDT.

不幸的是,当invokeLater()调用paintComponent()时,我遇到了一个空指针异常.

Unfortunately I'm having a null pointer exception when the paintComponent() is called by the invokeLater().

我的代码如下:

    @Override
public void paintComponent(Graphics graph) {
    //At first paint (which can be lengthy for large charts), show "please wait" message
    if (! isPainted){
        isPainted = true;
        dialog = new JDialog();
        dialog.setUndecorated(true);
        JPanel panel = new JPanel();
        panel.add(new JLabel("Please wait"));
        panel.add(new JLabel("Please wait !!!!!!!!!!!!!!!!!!!!!!!!!!!!!"));
        dialog.add(panel);
        dialog.pack();
        GuiHelper.centerDialog(dialog); //Custom code to center the dialog on the screen
        dialog.setVisible(true);
        dialog.repaint();
        RunnableRepaintCaller r = new RunnableRepaintCaller(this, graph, dialog);
        SwingUtilities.invokeLater(r);
    }
    else super.paintComponent(graph); //NULL POINTER EXCEPTION HERE (invoked by runnable class)
}

可运行类为:

public class RunnableRepaintCaller implements Runnable{
private ChartPanel target;
private Graphics g;
private JDialog dialog;

public RunnableRepaintCaller(ChartPanel target, Graphics g, JDialog dialog){
    this.target = target;
    this.g = g;
    this.dialog = dialog;
}

@Override
public void run() {
    System.out.println(g);
    target.paintComponent(g);
    dialog.dispose();
}
}

再次,任何指针将不胜感激!

Again, any pointer would be much appreciated !

托马斯

推荐答案

这里是一个示例,但它使用了SwingWorker.您应该认真考虑使用此功能,因为如果操作系统以某种方式使您的框架无效,并且在EDT(事件调度线程)上完成了JFreeChart的加载,那么您的GUI将会冻结.

Here is an example and/but it uses SwingWorker. You should seriously consider using this because if somehow the OS invalidates your frame and the loading of your JFreeChart is done on the EDT (Event Dispatching Thread), then your GUI will look frozen.

它还允许您在处理数据时提供更好的用户反馈. (很抱歉,如果代码有点长,但是大多数有趣的代码在initUI和SwingWorker中).

It also allows you to give better user feedback while you are processing the data. (sorry if the code is a bit long but most of the interesting code is in the initUI and the SwingWorker).

注意:您可以使用JLayer(如果使用Java 7)来代替对话框,但这在我的示例中是不必要的.

Note: instead of the dialog, you could use the JLayer (if you use Java 7), but this was unnecessary in my example.

该代码的灵感来自 http://www.vogella.com/articles/JFreeChart/article.html

/**
 * This code was directly taken from: http://www.vogella.com/articles/JFreeChart/article.html
 * All credits goes to him for this code.
 *
 * Thanks to him.
 */

import java.util.List;

import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PiePlot3D;
import org.jfree.data.general.DefaultPieDataset;
import org.jfree.data.general.PieDataset;
import org.jfree.util.Rotation;

public class PieChart extends JFrame {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                initUI();
            }
        });
    }

    protected static void initUI() {
        // First we create the frame and make it visible
        final PieChart demo = new PieChart("Comparison");
        demo.setSize(500, 270);
        demo.setVisible(true);
        // Then we display the dialog on that frame
        final JDialog dialog = new JDialog(demo);
        dialog.setUndecorated(true);
        JPanel panel = new JPanel();
        final JLabel label = new JLabel("Please wait...");
        panel.add(label);
        dialog.add(panel);
        dialog.pack();
        // Public method to center the dialog after calling pack()
        dialog.setLocationRelativeTo(demo);

        // allowing the frame and the dialog to be displayed and, later, refreshed
        SwingWorker<JFreeChart, String> worker = new SwingWorker<JFreeChart, String>() {

            @Override
            protected JFreeChart doInBackground() throws Exception {
                publish("Loading dataset");
                // simulating the loading of the Dataset
                try {
                    System.out.println("Loading dataset");
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // This will create the dataset
                PieDataset dataset = demo.createDataset();
                publish("Loading JFreeChart");
                // simulating the loading of the JFreeChart
                try {
                    System.out.println("Loading JFreeChart");
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // based on the dataset we create the chart
                JFreeChart chart = demo.createChart(dataset, "Which operating system are you using?");
                // we put the chart into a panel
                return chart;
            }

            @Override
            protected void process(List<String> chunks) {
                label.setText(chunks.get(0));
                dialog.pack();
                dialog.setLocationRelativeTo(demo);
                dialog.repaint();
            }

            @Override
            protected void done() {
                try {
                    // Retrieve the created chart and put it in a ChartPanel
                    ChartPanel chartPanel = new ChartPanel(this.get());
                    // add it to our frame
                    demo.setContentPane(chartPanel);
                    // Dispose the dialog.
                    dialog.dispose();
                    // We revalidate to trigger the layout
                    demo.revalidate();
                    // Repaint, just to be sure
                    demo.repaint();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        };
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                     worker.execute();
            }
        });
        dialog.setVisible(true);
    }

    public PieChart(String applicationTitle) {
        super(applicationTitle);
    }

    /** * Creates a sample dataset */

    private PieDataset createDataset() {
        DefaultPieDataset result = new DefaultPieDataset();
        result.setValue("Linux", 29);
        result.setValue("Mac", 20);
        result.setValue("Windows", 51);
        return result;

    }

    /** * Creates a chart */

    private JFreeChart createChart(PieDataset dataset, String title) {

        JFreeChart chart = ChartFactory.createPieChart3D(title, // chart title
                dataset, // data
                true, // include legend
                true, false);
        PiePlot3D plot = (PiePlot3D) chart.getPlot();
        plot.setStartAngle(290);
        plot.setDirection(Rotation.CLOCKWISE);
        plot.setForegroundAlpha(0.5f);
        return chart;

    }

}

这篇关于如何创建“请稍候"?在组件绘制时摆动对话框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 17:40