【问题标题】:Force JDialog to get visible before proccessing data?在处理数据之前强制 JDialog 可见?
【发布时间】:2012-04-07 10:25:30
【问题描述】:

我在 NetBeans 中创建了一个 JDialog 和一个自定义构造函数,如下所示:

public AnimatedProgress(java.awt.Frame parent, boolean modal, JTable table) {
    super(parent, modal);
    initComponents();
    setLocationRelativeTo(parent);
    progressLabel.setText("Collecting Table Data. . .");
    Object[][] data = getJTableData(table); // Simple method to collect data and store in Object[][] array
    progressLabel.setText("Processing Data. . .");
    processData(data);
    progressLabel.setText("Data Processed. . .");
}

现在我将这个JDialog 称为:

new AnimatedProgress(this, true, dataTable).setVisible(True);

我的问题是,当 Java 调用构造函数时,构造函数中的所有代码都会先执行,然后出现对话框并显示最终结果。

如何让我的JDialog先出现再处理方法:getTableData()processData()??

【问题讨论】:

  • 不要阻塞 EDT(事件调度线程)——当这种情况发生时,GUI 将“冻结”。而不是调用Thread.sleep(n) 实现一个Swing Timer 用于重复任务或SwingWorker 用于长时间运行的任务。有关详细信息,请参阅Concurrency in Swing
  • @AndrewThompson -- 是的,这实际上是主要问题。好吧,我知道swing.Timer,但是只有两个绝对不会重复的过程,而且,我不知道如何在这里申请SwingWorker。 . .你能用SwingWorker代码回答这个问题吗?
  • @Asif:请不要索要代码——这取决于你自己的创作。为什么不查看 Andrew Thompson 链接的教程并尝试创建自己的代码。然后,如果您遇到困难,请在此处发布您的尝试。
  • 好的,我会去的。 . .谢谢你:)
  • @Andrew Thompson 是对的。最好的解决方案是使用SwingWorker。请参阅我的答案,其中显示了使用 SwingWorker 的示例。

标签: java swing jdialog swingworker


【解决方案1】:

这是SwingWorker的示例用法:

public class BackgroundThread extends SwingWorker<Void, Void>
{
    private JTable table;

    public BackgroundThread(JTable table)
    {
        this.table = table;
    }

    @Override
    public Void doInBackground() throws Exception
    {
        /*
            If getJTableData() or processData() are not static,
            pass a reference of your class which has these methods
            and call them via that reference
        */
        Object[][] data = getJTableData(table);
        publish("Processing Data. . .");
        processData(data);
        publish("Data Processed. . .");
        return null;
    }

    @Override
    public void process(List<String> chunks)
    {
        for(String chunk : chunks) progressLabel.setText(chunk);
    }
}

然后将您的构造函数更改为:

public AnimatedProgress(java.awt.Frame parent, boolean modal, JTable table)
{
    super(parent, modal);
    initComponents();
    setLocationRelativeTo(parent);
    setVisible(true);
    new BackgroundThread(table).execute();
}

我没有测试它,但我希望它有效。

【讨论】:

  • 哦,非常感谢,我只需要你给出的结构代码:) 如果出现错误,我会处理。 . :)
  • @Asif 如果getJTableData()processData() 包含GUI 上的任何更改,请尝试在process() 方法中传输它,以避免GUI 冻结。
  • 我在声明process() 方法时遇到了这个错误:method does not override or implement a method from a supertype name clash: process(java.util.List&lt;java.lang.String&gt;) in BackgroundThread and process(java.util.List&lt;V&gt;) in javax.swing.SwingWorker have the same erasure, yet neither overrides the other
  • 在编辑行时:class BackgroundThread extends SwingWorker&lt;String, Void&gt;class BackgroundThread extends SwingWorker&lt;String, _String_&gt; 错误消除了,这里发生了什么?
  • 我已经成功执行了所有步骤,只剩下最后一个,在所有处理之后我必须自动dispose对话框,我该如何实现呢?或者有没有办法通过我的BackgroundThread 告诉EDT 是的,我已经完成了我的流程,现在你可以打电话给dispose()
【解决方案2】:

JDialog 在创建之前是不可见的 ==> 构造函数必须在可见性更改之前完全执行。
我认为您应该创建一个包含数据填充的 myInitialize() 方法。 首先,通过调用构造函数使对话框可见,之后您可以调用 myIntialize() 方法以使用正确的数据填充组件。

【讨论】:

  • 我应该在哪里调用这个myInitialize()方法?
  • 在构造函数调用之后。 AnimatedProgress progress = new AnimatedProgress(this, true, dataTable); progress.setVisible(true);进度.init();
  • 实际上 getTableData()processData() 方法中的整个代码与 JDailog 中的动画一起自我执行(我在这里跳过了 Timer 代码),我不能称之为我调用JDialog的事件的代码......我希望我对你很清楚:)
猜你喜欢
  • 2013-12-07
  • 1970-01-01
  • 1970-01-01
  • 2011-08-07
  • 2012-04-23
  • 2016-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多