为什么JFrame在一个案例中是空白而在另一个案例中不是? (简单的SwingWorker示例)

时间:2017-05-10 02:23:38

标签: java swing jframe

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

在此处添加此内容,因为评论时间过长:

我可以看到我不清楚。运行MaintTest / main时,带有Test按钮的JFrame不是问题。单击测试按钮时显示的JFrame是问题。

注释掉FileUtils.copyURLToFile尝试块会使第二个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");
}

}

1 个答案:

答案 0 :(得分:0)

感谢@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");
}

}

这很好用。