如何在组件绘制时创建“请稍候”Swing 对话框

2024-03-15

对于 Swing 来说仍然相对较新,但经过几个小时的搜索,我无法在网上找到答案,因此写了这篇文章(抱歉,如果已经回答但我忽略了它)。

我在 Swing 应用程序中使用 JFreeChart。有些图表相对较重(180k 数据点),并且 JFreeChart 的 ChartPanel 需要大约 6 秒来执行其第一个 PaintComponent()。

因此,我想在组件绘制时在对话框中显示“请稍候”消息(无需使用 SwingWorker 显示进度)。我尝试重写 PaintComponent 方法,但不幸的是该消息从未出现在屏幕上(我猜线程直接进入绘制图表,而不花时间绘制对话框)。

我的代码如下所示:

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

任何有关如何解决此问题/最佳实践的指示将不胜感激!

谢谢, 托马斯


UPDATE:

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

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

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

我的代码如下所示:

    @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();
}
}

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

Thomas


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

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

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

该代码的灵感很大来自http://www.vogella.com/articles/JFreeChart/article.html 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;

    }

}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在组件绘制时创建“请稍候”Swing 对话框 的相关文章

  • 如何在spring mvc中从控制器名称+操作名称获取映射的URL?

    是否有现有的解决方案可以从 Spring MVC3 中的 控制器名称 操作名称 获取映射的 URL 例如 asp net mvc 或 Rails 中的 UrlHelper 我觉得非常有用 thx 也许 你想要这样的东西 in your Co
  • 对话框上的 EditText 不返回任何文本

    我太累了 找不到错误 我没有发现任何错误 但我没有从 editText 收到任何文本 请看下面的代码 活动密码 xml
  • 无法使用maven编译java项目

    我正在尝试在 java 16 0 1 上使用 maven 构建 IntelliJ 项目 但它无法编译我的项目 尽管 IntelliJ 能够成功完成 在此之前 我使用maven编译了一个java 15项目 但我决定将所有内容更新到16 0 1
  • Spring安全“记住我”cookie在第一个请求中不可用

    我无法在登录请求后检索 Spring 记住我 cookie 但它在对受保护页面的下一个请求中工作正常 谁能告诉我怎样才能立即得到它 我在登录请求中设置了记住我的 cookie 但在 Spring 重定向回原始 受保护的 url 后无法检索它
  • 来自数据库的 jfreechart 散点图

    如何使用java中的jfreechart绘制mysql数据库表中数据的散点图 我使用过 Swing 库 任何链接都会有帮助 我搜索了谷歌但找不到理解的解决方案 如果您有代码 请提供给我 实际上我确实做了条形图并使用 jfreechart 绘
  • Java:使用 HttpURLConnection 的 HTTP PUT

    如何执行 HTTP PUT 我正在使用的类似乎认为它正在执行 PUT 但端点将其视为我执行了 GET 我做错了什么吗 URL url new URL https HttpURLConnection conn HttpURLConnectio
  • eclipse中导入项目文件夹图标

    我在 Eclipse 工作区中新导入的 Maven 项目有J and M项目文件夹顶部的图标 项目和包资源管理器 而其他导入的 Maven 项目只有一个J icon 有人可以解释其中的区别吗 该项目有J装饰器被称为 Java 项目和具有M装
  • 使用 RecyclerView 适配器在运行时更改布局屏幕

    我有两个布局文件 如下所示 如果列表中存在数据 则我显示此布局 当列表为空时 我会显示此布局 现在我想在运行时更改布局 当用户从列表中删除最后一项时 我想将布局更改为第二张图片中显示的 空购物车布局 In getItemCount Recy
  • 无法在 Spring Boot 测试中模拟 persistenceContext

    我正在使用带有 Mockito 框架的 spring boot 测试来测试我的应用程序 存储库类 EntityManager 之一作为参考 我的班级如下所示 Repository Transactional Slf4j public cla
  • Firestore - RecycleView - 图像持有者

    我不知道如何编写图像的支架 我已经设置了 2 个文本 但我不知道图像的支架应该是什么样子 你能帮我告诉我图像的文字应该是什么样子才能正确显示吗 holder artistImage setImageResource model getArt
  • 内存一致性 - Java 中的happens-before关系[重复]

    这个问题在这里已经有答案了 在阅读有关内存一致性错误的 Java 文档时 我发现与创建 发生 之前 关系的两个操作相关的点 当语句调用时Thread start 每个具有 与该语句发生之前的关系也有一个 与 new 执行的每个语句之间发生的
  • 如何让spring为JdbcMetadataStore创建相应的schema?

    我想使用此处描述的 jdbc 元数据存储 https docs spring io spring integration docs 5 2 0 BUILD SNAPSHOT reference html jdbc html jdbc met
  • 如何在android中设置多个闹钟,在这种情况下最后一个闹钟会覆盖以前的闹钟

    我正在开发一个Android应用程序 用户可以在其中设置提醒时间 但我在以下代码中遇到一个问题 即最后一个警报会覆盖之前的所有警报 MainActivity java public void setreminders DatabaseHan
  • 如何获取 WebElement 的父级[重复]

    这个问题在这里已经有答案了 我试过了 private WebElement getParent final WebElement webElement return webElement findElement By xpath 但我得到
  • 如何将 Jfreechart(饼图)添加到 netbeans 的面板中

    我正在使用 netbeans gui 编辑器 并且正在尝试添加一个本身位于内部框架中的 Jfreechart 并且这个内部框架我想将其添加到面板中 正如您在此图中看到的那样 抱歉 我无法直接发布图像 因为我新手 http www flick
  • 如何记录来自 Akka (Java) 的所有传入消息

    在 Scala 中 您可以使用 LoggingReceive 包装接收函数 如何通过 Java API 实现相同的目标 def receive LoggingReceive case x do something Scala API 有Lo
  • 如何在 Quartz 调度程序中每 25 秒运行一次?

    我正在使用 Java 的 Quartz Scheduling API 你能帮我使用 cron 表达式每 25 秒运行一次吗 这只是一个延迟 它不必总是从第 0 秒开始 例如 序列如下 0 00 0 25 0 50 1 15 1 40 2 0
  • 解决错误javax.mail.AuthenticationFailedException

    我不熟悉java中发送邮件的这个功能 我在发送电子邮件重置密码时遇到错误 希望你能给我一个解决方案 下面是我的代码 public synchronized static boolean sendMailAdvance String emai
  • Java:拆箱整数时出现空指针异常?

    此代码导致空指针异常 我不知道为什么 private void setSiblings PhylogenyTree node Color color throws InvalidCellNumberException PhylogenyTr
  • Android 和 Java 中绘制椭圆的区别

    在Java中由于某种原因Ellipse2D Double使用参数 height width x y 当我创建一个RectF在Android中参数是 left top right bottom 所以我对适应差异有点困惑 如果在 Java 中创

随机推荐

  • 字符串性能 - Windows 10 下的 Python 2.7 与 Python 3.4 对比 Ubuntu

    Use case一个简单的函数 用于检查特定字符串是否在另一个字符串中的位置为 3 的倍数 请参阅此处现实世界的例子 https en wikipedia org wiki Stop codon 在 DNA 序列中寻找终止密码子 功能 sl
  • Android SD卡目录文件夹名称列表

    如何获取 SD 卡上特定目录中的所有文件夹 不是文件 的名称 例如 所有子文件夹名称 sdcard first level folder 我需要文件夹名称 因此我可以将完整路径 字符串 传递给方法 然后将其压缩 zip Thanks 我想你
  • Java SE 6 中 Sun JVM 的默认最大堆大小是多少?

    Java SE 6 中 Sun JVM 的默认最大堆大小是多少 即相当于设置 Xmx 看起来对于带有服务器级机器的 Java SE 5 it s http java sun com j2se 1 5 0 docs guide vm gc e
  • jsf 安全约束在用户未登录时保护链接?

    我有一个定义了安全约束的 JSF2 GlassFish 3 0 应用程序 示例如下 我的问题是 我有一个 注册 链接 当用户登录时不应访问该链接 也就是说 如果他们尝试点击 signup jsf 如果他们已登录 他们应该能够访问 所以如果他
  • Rails 模型 has_many 具有多个foreign_keys

    对 Rails 来说相对较新 并尝试使用具有姓名 性别 father id 和 mother id 2 个父母 的单个 Person 模型来建模非常简单的家庭 树 下面基本上是我想做的 但显然我不能在 has many 中重复 childr
  • 是否可以从 Android 应用程序执行 Shell 脚本

    我一直在尝试 Android 终端模拟器 Termux 这是一款优秀的应用程序 无需 root 访问即可访问 Android 操作系统 我希望能够实现的是从同一设备上安装的另一个 Android 应用程序中执行 Termux 中的脚本 命令
  • Storm程序的执行流程

    我是 Storm 的新手 试图了解不同方法的执行流程spout to bolt 就像spout有不同的方法一样 下一个元组 open 声明输出字段 启用 停用 Bolt 有类似的方法 准备 执行 清理 声明输出字段 那么谁能告诉我这些方法的
  • 将数据传递给 Polymer 元素

    使用 Web UI 时 我可以将数据传递给组件 如下所示
  • 卷积神经网络的 float16 与 float32

    标准是float32 但我想知道在什么条件下可以使用float16 我比较了运行相同的 covnet 和两种数据类型 没有发现任何问题 对于大型数据集 我更喜欢 float16 因为我可以更少担心内存问题 令人惊讶的是 使用 16 位是完全
  • 在docker中挂载两个嵌套的只读挂载点

    我有一个docker compose文件运行 PHP 并以嵌套方式安装一些卷 它已经工作了两年了 最近我又尝试了一次 但失败了 至少在 Docker for WSL 2 上是这样 以下是 docker compose 文件中挂载的卷 vol
  • 如何设置 git 提交消息的模式?

    我想限制提交的人具有特定的提交消息格式 我该怎么做 例如 Pair Name Story Number Commit Message 有一个pre commit msg or commit msg钩子 你可以使用 http www kern
  • 使用函数给定的值初始化 numpy 数组的最快方法

    我主要对 d1 d2 numpy 数组 矩阵 感兴趣 但这个问题对于具有更多轴的数组来说是有意义的 我有函数 f i j 我想通过该函数的某些操作来初始化数组 A np empty d1 d2 for i in range d1 for j
  • JFrame java中的无限消失-重新出现循环

    作为继这个帖子 https stackoverflow com questions 34593471 why do i need to reset settext in a jlabel to prevent errors 34598241
  • 如何获取侧边栏下拉列表中所有工作表的列表

    我正在谷歌工作表的侧边栏菜单中工作 以设置我的脚本中需要的一些变量 我的脚本已经可以运行了 这很简单 在提交表单时 它将在我的日历中创建一个事件 但是 为了简化脚本的安装 我想在侧边栏中显示一个下拉列表 其中包含工作表中所有工作表的名称 我
  • 克隆Conda根环境不会克隆conda和condo-build

    我在 OS X El Capitan 10 11 4 上使用 conda 4 2 9 我使用以下命令克隆了根环境 conda create n rootclone clone root 它给出了以下消息 The following pack
  • 为什么 spread() 方法在 Sequelize 中不起作用?

    我正在使用一个Sequelize for my node js应用程序 我用findOrCreate 方法创建新用户 如果不存在 据此docs http docs sequelizejs com manual tutorial models
  • 如何更改微调器背景颜色?

    如何更改微调器背景颜色 这种黑色来自风格 如何更改弹出窗口的样式颜色 我想将背景颜色更改为白色而不是黑色 我该如何改变 spinnner
  • 使用 Moose 时在构造时分配方法体的最佳方法是什么?

    我在用着Moose 具体来说MooseX Declare 创建一个迭代器对象 Iter其中有一个next前进状态并返回的方法0 or 1根据需要使用在while陈述 我遇到的问题是 根据构造参数之一的存在 next需要执行两组截然不同的操作
  • 如何将 jquery ui 与 Bower 一起使用?

    我正在尝试yeoman http yeoman io and bower http bower io 我使用以下命令创建了一个 yeoman webapp yo webapp 我想用jqueryui http jqueryui com 所以
  • 如何在组件绘制时创建“请稍候”Swing 对话框

    对于 Swing 来说仍然相对较新 但经过几个小时的搜索 我无法在网上找到答案 因此写了这篇文章 抱歉 如果已经回答但我忽略了它 我在 Swing 应用程序中使用 JFreeChart 有些图表相对较重 180k 数据点 并且 JFreeC