【问题标题】:Why is JFrame blank in one case but not the other? (Simple SwingWorker example)为什么 JFrame 在一种情况下是空白的,而在另一种情况下却不是? (简单的 SwingWorker 示例)
【发布时间】:2017-05-16 03:43:47
【问题描述】:

================================================

由于评论太长,所以在此处添加:

我可以看出我不清楚。运行 MaintTest/main 时,JFrame with Test 按钮不是问题。单击测试按钮时显示的 JFrame 就是问题所在。

注释掉 FileUtils.copyURLToFile try 块会使第二个 JFrame 显示如此短暂,不清楚它是否显示标签和 progbar。 (带有测试按钮的初始 JFrame 正常显示,当我单击测试按钮时,第二个 JFrame 会立即出现并消失。带有测试按钮的 JFrame 保持不变。我不重现“测试按钮 6连续几次”。这听起来可能是设置错误?)

是的,copyURLToFile 是阻塞的,但是我在调​​用 copyURLToFile 之前启动了第二个 JFrame 的并发显示,所以它不应该在单独的线程中运行吗?我有理由知道它确实如此。在派生此代码的原始应用程序中,第二个 JFrame 会根据需要显示有时

JFrame 显示有时总是通过最后调用 setVisible 来回答,但这并不能解决我的情况。这似乎与我不理解的并发和 Swing 有关。

================================================

通常我可以通过谷歌找到答案(通常在 SO)。我一定在这里遗漏了什么。

我已将其缩减为我实际代码的一小部分,但仍然没有开悟。对不起,如果它仍然有点大,但很难进一步浓缩。

有 3 个 java 文件。这引用了 commons-io-2.5.jar。我正在 Eclipse Neon 中编码/运行。

如果我运行ProgressBar/main(),我会看到JFrame 的内容。如果我运行MainTest/main() 我不会。这是 3 个文件(请原谅一些缩进异常——SO UI 和我不同意这些事情):

MainTest

public class MainTest {

public static void main(String[] args) {
    MainFrame mainFrame = new MainFrame();
}

}

MainFrame

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

import org.apache.commons.io.FileUtils;

public class MainFrame extends JFrame implements ActionListener {

JButton jButton = new JButton();

public MainFrame() {
    // Set up the content pane.
    Container contentPane = this.getContentPane();
    contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
    jButton.setAlignmentX(Component.CENTER_ALIGNMENT);
    jButton.setText("Test");
    jButton.setActionCommand("Test");
    jButton.addActionListener(this);
    contentPane.add(jButton);
    setup();
}

private void setup() {
    Toolkit tk;
    Dimension screenDims;
    tk = Toolkit.getDefaultToolkit();
    screenDims = tk.getScreenSize();
    this.setLocation((screenDims.width - this.getWidth()) / 2, (screenDims.height - this.getHeight()) / 2);

    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.pack();
    this.setVisible(true);
}

public static void downloadExecutable(String str) {
    URL url = null;
    try {
        url = new URL("http://pegr-converter.com/download/test.jpg");
    } catch (MalformedURLException exc) {
        JOptionPane.showMessageDialog(null, "Unexpected exception: " + exc.getMessage());
        return;
    }
    if (url != null) {
        String[] options = { "OK", "Change", "Cancel" };
        int response = JOptionPane.NO_OPTION;
        File selectedFolder = new File(getDownloadDir());
        File selectedLocation = new File(selectedFolder, str + ".jpg");
        while (response == JOptionPane.NO_OPTION) {
            selectedLocation = new File(selectedFolder, str + ".jpg");
            String msgStr = str + ".jpg will be downloaded to the following location:\n"
                    + selectedLocation.toPath();
            response = JOptionPane.showOptionDialog(null, msgStr, "Pegr input needed",
                    JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0]);
            if (response == JOptionPane.NO_OPTION) {
                // Prompt for file selection.
                JFileChooser fileChooser = new JFileChooser();
                fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                fileChooser.setCurrentDirectory(selectedFolder);
                fileChooser.showOpenDialog(null);
                selectedFolder = fileChooser.getSelectedFile();
            }
        }
        if (response == JOptionPane.YES_OPTION) {
            int size = 0;
            URLConnection conn;
            try {
                conn = url.openConnection();
                size = conn.getContentLength();
            } catch (IOException exc) {
                System.out.println(exc.getMessage());
            }
            File destination = new File(selectedFolder, str + ".jpg");
            ProgressBar status = new ProgressBar("Downloading " + str + ".jpg", destination, size);
            try {
                FileUtils.copyURLToFile(url, destination, 10000, 300000);
            } catch (IOException exc) {
                JOptionPane.showMessageDialog(null, "Download failed.");
                return;
            }
            status.close();
        }
    }
}

public static String getDownloadDir() {
    String home = System.getProperty("user.home");
    File downloadDir = new File(home + "/Downloads/");
    if (downloadDir.exists() && !downloadDir.isDirectory()) {
        return home;
    } else {
        downloadDir = new File(downloadDir + "/");
        if ((downloadDir.exists() && downloadDir.isDirectory()) || downloadDir.mkdirs()) {
            return downloadDir.getPath();
        } else {
            return home;
        }
    }
}

@Override
public void actionPerformed(ActionEvent arg0) {
    downloadExecutable("test");
}

}

ProgressBar

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Timer;
import java.util.TimerTask;

import javax.imageio.ImageIO;
import javax.swing.BoxLayout;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.SwingConstants;

import org.apache.commons.io.FileUtils;

public class ProgressBar {

private String title;
private File outputFile;
private int size;
private ProgressTimerTask task;

JFrame frame;
JLabel jLabelProgressTitle;
JProgressBar jProgressBarProportion;

public ProgressBar(String title, File output, int size) {
    this.title = title;
    this.outputFile = output;
    this.size = size;
    frame = new JFrame("BoxLayoutDemo");

    jProgressBarProportion = new JProgressBar();
    jProgressBarProportion.setPreferredSize(new Dimension(300, 50));

    jLabelProgressTitle = new JLabel();
    jLabelProgressTitle.setHorizontalAlignment(SwingConstants.CENTER);
    jLabelProgressTitle.setText("Progress");
    jLabelProgressTitle.setPreferredSize(new Dimension(300, 50));

    //Set up the content pane.
    Container contentPane = frame.getContentPane();
    contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
    jLabelProgressTitle.setAlignmentX(Component.CENTER_ALIGNMENT);
    contentPane.add(jLabelProgressTitle);
    jProgressBarProportion.setAlignmentX(Component.CENTER_ALIGNMENT);
    contentPane.add(jProgressBarProportion);

    setup();

    task = new ProgressTimerTask(this, outputFile, size);
    Timer timer = new Timer();
    timer.scheduleAtFixedRate(task, 0, 500);
}

private void setup() {
    Toolkit tk;
    Dimension screenDims;

    frame.setTitle("Test");

    tk = Toolkit.getDefaultToolkit();
    screenDims = tk.getScreenSize();
    frame.setLocation((screenDims.width - frame.getWidth()) / 2, (screenDims.height - frame.getHeight()) / 2);

    jLabelProgressTitle.setText(title);
    jProgressBarProportion.setVisible(true);
    jProgressBarProportion.setMinimum(0);
    jProgressBarProportion.setMaximum(size);
    jProgressBarProportion.setValue((int) outputFile.length());

    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    frame.pack();
    frame.setVisible(true);
}

public void close() {
    task.cancel();
    frame.dispose();
}

public static void main(String[] args) throws InterruptedException {
    ProgressBar progBar = new ProgressBar("Test Title", new File(MainFrame.getDownloadDir() + "test.jpg"), 30000);
    Thread.sleep(3000);
    progBar.close();
}

}

class ProgressTimerTask extends TimerTask {

ProgressBar frame;
File outputFile;
int size;

public ProgressTimerTask(ProgressBar progressBar, File outputFile, int size) {
    this.frame = progressBar;
    this.outputFile = outputFile;
    this.size = size;
}

public void run() {
    frame.jProgressBarProportion.setValue((int) outputFile.length());
    System.out.println("Running");
}

}

【问题讨论】:

  • 尝试在 Event Dispatch Thread 上启动两个 GUI,并在 main 方法中取消休眠。
  • 你的mainFrame 对我来说很好用
  • 注释掉FileUtils及相关功能后,你试过了吗?我确实看到了一个Test 按钮,连续 6 次。
  • 我可以告诉你,你可能不会看到ProgressBar 框架,因为FileUtils.copyURLToFile 会阻塞直到它完成,在这种情况下,你真的应该使用SwingWorker
  • 睡眠是在有效的情况下,所以我认为这与为什么其他情况(没有睡眠)不起作用无关。

标签: java swing jframe


【解决方案1】:

感谢@MadProgrammer 的评论:

我可以告诉你,你可能不会看到 ProgressBar 框架,因为 FileUtils.copyURLToFile 会阻塞直到它完成,在这种情况下,你真的应该使用 SwingWorker

我在教程https://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html 中阅读了有关 SwingWorker 的信息,随后将 MainFrame.java 模块修改为如下所示:

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingWorker;

import org.apache.commons.io.FileUtils;

public class MainFrame extends JFrame implements ActionListener {
JButton jButton = new JButton();
static ProgressBar status;
static URL url;

public MainFrame() {
    // Set up the content pane.
    Container contentPane = this.getContentPane();
    contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
    jButton.setAlignmentX(Component.CENTER_ALIGNMENT);
    jButton.setText("Test");
    jButton.setActionCommand("Test");
    jButton.addActionListener(this);
    contentPane.add(jButton);
    setup();
}

private void setup() {
    Toolkit tk;
    Dimension screenDims;
    tk = Toolkit.getDefaultToolkit();
    screenDims = tk.getScreenSize();
    this.setLocation((screenDims.width - this.getWidth()) / 2, (screenDims.height - this.getHeight()) / 2);

    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.pack();
    this.setVisible(true);
}

public static void downloadExecutable(String str) {
    url = null;
    try {
        url = new URL("http://pegr-converter.com/download/test.jpg");
    } catch (MalformedURLException exc) {
        JOptionPane.showMessageDialog(null, "Unexpected exception: " + exc.getMessage());
        return;
    }
    if (url != null) {
        String[] options = { "OK", "Change", "Cancel" };
        int response = JOptionPane.NO_OPTION;
        File selectedFolder = new File(getDownloadDir());
        File selectedLocation = new File(selectedFolder, str + ".jpg");
        while (response == JOptionPane.NO_OPTION) {
            selectedLocation = new File(selectedFolder, str + ".jpg");
            String msgStr = str + ".jpg will be downloaded to the following location:\n"
                    + selectedLocation.toPath();
            response = JOptionPane.showOptionDialog(null, msgStr, "Pegr input needed",
                    JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0]);
            if (response == JOptionPane.NO_OPTION) {
                // Prompt for file selection.
                JFileChooser fileChooser = new JFileChooser();
                fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                fileChooser.setCurrentDirectory(selectedFolder);
                fileChooser.showOpenDialog(null);
                selectedFolder = fileChooser.getSelectedFile();
            }
        }
        if (response == JOptionPane.YES_OPTION) {
            int size = 0;
            URLConnection conn;
            try {
                conn = url.openConnection();
                size = conn.getContentLength();
            } catch (IOException exc) {
                System.out.println(exc.getMessage());
            }
            //System.out.println("javax.swing.SwingUtilities.isEventDispatchThread=" + javax.swing.SwingUtilities.isEventDispatchThread());
            File destination = new File(selectedFolder, str + ".jpg");
            status = new ProgressBar("Downloading " + str + ".jpg", destination, size);
            SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
                @Override
                protected Void doInBackground() throws Exception {
                    try {
                        FileUtils.copyURLToFile(url, destination, 10000, 300000);
                    } catch (IOException exc) {
                        JOptionPane.showMessageDialog(null, "Download failed.");
                    }
                    return null;
                }
                public void done() {
                    status.close();
                }
            };
            worker.execute();
        }
    }
}

public static String getDownloadDir() {
    String home = System.getProperty("user.home");
    File downloadDir = new File(home + "/Downloads/");
    if (downloadDir.exists() && !downloadDir.isDirectory()) {
        return home;
    } else {
        downloadDir = new File(downloadDir + "/");
        if ((downloadDir.exists() && downloadDir.isDirectory()) || downloadDir.mkdirs()) {
            return downloadDir.getPath();
        } else {
            return home;
        }
    }
}

@Override
public void actionPerformed(ActionEvent arg0) {
    downloadExecutable("test");
}

}

效果很好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-12
    • 2019-11-02
    • 2022-12-01
    • 2013-12-28
    • 1970-01-01
    • 1970-01-01
    • 2020-03-31
    相关资源
    最近更新 更多