【问题标题】:Wait for Swing ui construction completion, mirror of Swingworker等待 Swing ui 构建完成,Swingworker 的镜像
【发布时间】:2018-01-26 20:37:32
【问题描述】:

我需要一个 SwingWorker 的反面。我有一个线程应该启动一个复杂的 UI 构建过程,然后继续其他的东西。如果任何其他线程应该尝试通过 getter 引用该 UI,则 getter 应该阻塞,直到 UI 完成构建。这个模式怎么样:

public class Standard {

    private JFrame uiFrame = null;
    private final Object lock = new Object();

    public void makeUI() {
        Runnable onEDT = () -> {
            synchronized (lock) {
                uiFrame = new ComplexJFrameSubclass();
                uiFrame.setup(Standard.this);
                lock.notify();
            }
        };
        javax.swing.SwingUtilities.invokeLater(onEDT);
    }

    public JFrame getUIFrame() {
        if (uiFrame == null) {
            synchronized (lock) {
                try {
                    lock.wait();
                } catch (InterruptedException ex) {
                    LOG.log(Level.SEVERE, ex.getMessage(), ex);
                }
            }
        }
        return uiFrame;
    }
}

【问题讨论】:

  • 显示模态 JDialog,构建 GUI,做背景工作,完成后,清除模态对话框(在回调方法中),并显示 GUI。
  • 我很生气地发现那个 invokeLater(onEDT);稍后被称为。事件线程在 makeUI 之前到达 getGUIFrame()。所以我不认为这种方法会奏效。接下来我将尝试在 getGUI() 中懒惰地构建 UI。
  • 我仍然不能 100% 确定您在做什么以及为什么。您能否让您的问题更加具体,解释代码实际在做什么以及为什么。还可以考虑发布一个有效的minimal reproducible example,说明您正在尝试做的事情以及我们可以使用的内容。
  • 你提到的方法,getGUIFrame() & getGUI(),我们甚至都没有看到,所以很难给你任何解释为什么你当前的代码表现得如此。
  • 而且 Swing 是单线程的,这使得这段代码看起来不必要地复杂。在我们知道更多之前,我怀疑这实际上是一个XY Problem

标签: java multithreading swing concurrency


【解决方案1】:

这似乎是我想要的:

/**
 * Example of a class starting construction of the UI on the EDT, but making 
 * that UI available through a getter, without race problems.
 * Pretend the JFrame being constructed is huge, complicated, and does a lot
 * of slow drawing stuff.
 */
public class Standard implements PropertyChangeListener {

    private JFrame uiFrame;
    private final Object _lock = new Object();

    public Standard makeUI() {
        if (uiFrame != null) {
            return this;
        }
        if (SwingUtilities.isEventDispatchThread()) {
            makeUISynched();
        } else {
            Runnable onEDT = () -> {
                makeUISynched();
            };
            javax.swing.SwingUtilities.invokeLater(onEDT);
        }
        return this;
    }

    private Standard makeUISynched() {
        synchronized (_lock) {
            uiFrame = new JFrame();
            uiFrame.addPropertyChangeListener(this);
            return this;
        }
    }

    /**
     * This is now thread safer, if it is called before the UI is constructed,
     * It will create the UI itself, and wait for completion.
     * @return The JFrame UI.
     **/
    public final JFrame getUIFrame() {
        if (uiFrame == null) {
            if (SwingUtilities.isEventDispatchThread()) {
                makeUISynched();
            } else {
                Runnable onEDT = () -> {
                    makeUISynched();
                };
                try {
                    SwingUtilities.invokeAndWait(onEDT);
                } catch (InterruptedException | InvocationTargetException ex) {
                    ex.printStackTrace();
                }
            }
        }
        return uiFrame;
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
    }

}

【讨论】:

    猜你喜欢
    • 2011-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-06
    • 1970-01-01
    • 2013-01-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多