SwingWorker中JProgressBar无法更新,但调试正常

3
这个问题让我苦恼了两天。我好像无法使JProgressBar正确更新,也不知道为什么。我已经阅读了并测试了并发和SwingWorker教程,使用简单代码在程序外部进行测试并能够正常运行。我理解了这些概念,但是因为代码已经被多次重写,我看不出为什么它不起作用。我会发布一个尽可能使用我的程序代码的SSCE,并在这里尽力解释。

基本上,我有一个自动更新/安装程序,用于更新和/或安装“魔兽世界”插件到我们客户的电脑上。'更新器'做的第一件事就是检查服务器是否与服务器上的更新程序安装程序版本相同。这非常顺利!实际上整个更新程序都工作得很好,除了这一个问题。如果更新程序发现服务器的版本号与更新程序的版本号不同,则会从服务器下载安装程序(在zip中),解压缩它,从包含在zip中的exe文件开始安装,然后关闭当前打开的更新程序,以便安装可以正确完成。

所以我在自我更新的卡片上放置了一个进度条(使用cardLayout来显示更新器,SelfUpdate,Login和AddonList三个不同卡片),以及JProgressBar下面的JTextArea。它查询服务器上的版本号,并将该版本与当前安装的更新程序版本进行比较。如果版本相同,则切换到登录卡片并继续进行下一步,到目前为止都很好,如果版本不同,则向服务器发送查询,并将zip文件发送回更新器以供处理。

这就是它不起作用的地方。zip文件大小合适,当然我想显示此下载的进度。zip文件下载很好(在SwingWorker doInBackground()方法中运行),然后更新程序将installer.exe文件解压缩到客户系统驱动器上的文件夹中,使用Runtime启动并启动installer.exe,弹出安装屏幕,然后使用System.exit(0)关闭当前更新程序。所有这些都可以工作,但JProgressBar本身将不会更新。它始终保持在0%。此外,taskOutput JTextArea也不会更新,但主要问题是进度条不会更新。如果可以修复这个问题而不更新JTextArea,我可以容忍这种情况。(也尝试在文本区域的位置放置JLabel但没有成功)

所以我知道我做错了什么,但我无法想象是什么。以下是发生“魔法”部分的代码。 :) 如果我在这里逐步解释,请原谅我。

Controller.java处理程序的所有流程,以下是你需要查看的部分。

// Imports packages needed for use in this file.
import javax.swing.*;
import java.awt.CardLayout;
import java.io.*;
// class instantiation
public class Controller {

// Variables needed for use in this class
private static Updater util;
private static int loginReturnState = 0;
/**
*   Single contructor for this class
*/
public Controller() {

}


/**
*   Main method which runes everything in the updater program
*
*/
public static void main(String[] args) {
    util = new Updater();
    // Schedule a job for the event dispatch thread.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {

            // setup a new GUI
            util.createGUI();
            JFrame rFrame = util.getRootFrame();                
            JPanel gFrame = util.getCardLayoutFrame();
            CardLayout cards = (CardLayout) gFrame.getLayout();
            cards.show(gFrame, "UpdateUpdaterPanel");

            rFrame.pack();
            rFrame.setLocationRelativeTo(null);
            rFrame.setVisible(true);

            SelfUpdater selfUp = new SelfUpdater();             
            int needUpdate = selfUp.checkForUpdate();                                       if (needUpdate == 2) {// Update available for download. Download it.
                selfUp.downloadUpdate();

            } 


        }
    });


}
}

好的,下一个文件是Updater类。为了将代码放在这里,希望能够编译并显示问题,我需要将这个类放在那里,否则我在uPdater类中拥有的实用方法将不会存在于被调用的范围内,而我广泛地使用它们。

// Packages needed for use in this file
import javax.swing.*;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.*;
import java.awt.CardLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseAdapter;
import java.io.*;


// Class instantiation
public class Updater {

// These final variables are set to the path for each of the images used
public static final String BG_IMAGE_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\background.png";
public static final String APP_ICON_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\app-icon.png";
public static final String CLOSE_IMAGE_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\close.png";
public static final String FINOFF_IMAGE_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\FinishedOff.png";
public static final String FINON_IMAGE_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\FinishedOn.png";
public static final String ICON_IMAGE_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\icon.png";
public static final String ICON64_IMAGE_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\icon64x64.png";
public static final String ICON256_IMAGE_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\icon256x256.png";
public static final String INSTOFF_IMAGE_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\InstallUpdatesOFF.png";
public static final String INSTON_IMAGE_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\InstallUpdatesON.png";
public static final String LOGO_IMAGE_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\logo.png";
public static final String MIN_IMAGE_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\minimize.png";
public static final String PROGBACK_IMAGE_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\ProgressBackground.png";
public static final String PROGBAR_IMAGE_PATH = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\ProgressBar.png";
public static final String INSTRUCTIONS_BUTTON = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\instructions.png";
public static final String PURCHASE_BUTTON = "F:\\Java Programs\\Updater\\src\\com\\dynastyaddons\\updater\\images\\Purchase.png";
// These are various final variables for use throughout the updater
public static final String URL_CONNECT = "http://dynastyaddons.com/api/index2.php?";
public static final String TITLE_TEXT = "Dynasty Updater";
public static final int BUFFER_SIZE = 4096;
public static final double UPDATER_VERSION = 1.1;

// Public variables needed for this class workings
private static JFileChooser fc;
private static JFrame rootFrame;

// Private variables for this class use alone
private static String PHPSessionID;
private static boolean debugToggle = true;
private CardLayout cards;
private JPanel guiFrame;
private Point mouseDownCompCoords;
private Login login;
private Addons addons;

/**
*   Sole contructor. (For invocation by subclass contructors, typically implicit.)
*/
public Updater() {
    // First instantiate any variables needed
    PHPSessionID = "notset";
    guiFrame = new JPanel();
    cards = new CardLayout();
    guiFrame.setLayout(cards);
}


// Various methods follow
/**
*   This will create the root gui for showing in the main method
*
*/
public void createGUI() {
    rootFrame = new JFrame();
    SpringLayout rootLayout = new SpringLayout();

    // setup root frame
    rootFrame.setUndecorated(true);
    rootFrame.setBackground(new Color(0,0,0,0));
    rootFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    rootFrame.setPreferredSize(new Dimension(800,600));
    rootFrame.setTitle(TITLE_TEXT);

    // add the background image
    JLabel bg = new JLabel(new ImageIcon(BG_IMAGE_PATH));
    bg.setLayout(rootLayout);
    rootFrame.add(bg);

    // setup title bar
    mouseDownCompCoords = null;
    mouseDownCompCoords = null;
    rootFrame.addMouseListener(new MouseListener() {
        public void mouseReleased(MouseEvent e){ mouseDownCompCoords = null; }
        public void mousePressed(MouseEvent e){ mouseDownCompCoords = e.getPoint(); }
        public void mouseExited(MouseEvent e){}
        public void mouseEntered(MouseEvent e){ }
        public void mouseClicked(MouseEvent e){ }
    });
    rootFrame.addMouseMotionListener(new MouseMotionListener() {
        public void mouseMoved(MouseEvent e){}
        public void mouseDragged(MouseEvent e){
            Point currCoords = e.getLocationOnScreen();
            rootFrame.setLocation(currCoords.x - mouseDownCompCoords.x, currCoords.y - mouseDownCompCoords.y);
        }
    });

    // Display and place the logo
    JLabel logo = new JLabel(new ImageIcon(LOGO_IMAGE_PATH));
    bg.add(logo);

    // add Close and Minimize buttons
    JPanel cmButt = createCloseAndMinButtons();
    bg.add(cmButt);

    // create card frame
    guiFrame.setPreferredSize(new Dimension(800, 435));
    guiFrame.setOpaque(false);
    bg.add(guiFrame);

    // Constrain the parts of your BG
    rootLayout.putConstraint(SpringLayout.WEST, logo, 30, SpringLayout.WEST, rootFrame);
    rootLayout.putConstraint(SpringLayout.NORTH, logo, 70, SpringLayout.NORTH, rootFrame);
    rootLayout.putConstraint(SpringLayout.NORTH, cmButt, 0, SpringLayout.NORTH, rootFrame);
    rootLayout.putConstraint(SpringLayout.EAST, cmButt, 0, SpringLayout.EAST, rootFrame);
    rootLayout.putConstraint(SpringLayout.SOUTH, guiFrame, 0, SpringLayout.SOUTH, rootFrame);
    rootLayout.putConstraint(SpringLayout.WEST, guiFrame, 0, SpringLayout.WEST, rootFrame);
    rootLayout.putConstraint(SpringLayout.EAST, guiFrame, 0, SpringLayout.EAST, rootFrame);


    // Create self updater panel and get it ready to show
    SelfUpdater selfUp = new SelfUpdater();
    JPanel selfUpd = selfUp.getSelfUpdatePanel();

            // get the cardlayout and add the three panels to it, then show the self-updater to begin.

    guiFrame.add(selfUpd, "UpdateUpdaterPanel");    }

/**
*   Creates a panel which has the close and minimize buttons on it.
*/
private static JPanel createCloseAndMinButtons() {
    JPanel a = new JPanel();
    SpringLayout closeLO = new SpringLayout();
    a.setLayout(closeLO);
    a.setPreferredSize(new Dimension(150,150));
    a.setOpaque(false);

    // Close Button
    JButton cButt = new JButton(new ImageIcon(Updater.CLOSE_IMAGE_PATH));
    cButt.setBorderPainted(false);
    cButt.setContentAreaFilled(false);
    cButt.setFocusPainted(false);
    cButt.setOpaque(false);
    cButt.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) { System.exit(0); }
    });
    a.add(cButt);

    // Minimize Button
    JButton mButt = new JButton(new ImageIcon(Updater.MIN_IMAGE_PATH));
    mButt.setBorderPainted(false);
    mButt.setContentAreaFilled(false);
    mButt.setFocusPainted(false);
    mButt.setOpaque(false);
    mButt.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e) { rootFrame.setState(JFrame.ICONIFIED); }
    });
    a.add(mButt);

    // Constrain parts on panel
    closeLO.putConstraint(SpringLayout.EAST, cButt, 12, SpringLayout.EAST, a);
    closeLO.putConstraint(SpringLayout.NORTH, cButt, -2, SpringLayout.NORTH, a);
    closeLO.putConstraint(SpringLayout.EAST, mButt, 30, SpringLayout.WEST, cButt);
    closeLO.putConstraint(SpringLayout.NORTH, mButt, -2, SpringLayout.NORTH, a);

    // Return the jframe
    return a;

}

/**
*   Returns the guiFrame which holds the cardlayout for the changing of the panels.
*
*   @return JPanel  Returns the frame which holds the cardlayout.
*/
public JPanel getCardLayoutFrame() {
    return guiFrame; 
}   

/**
*   This will return the cardlayout for use in the controller.
*
*   @return CardLayout  Returns the cardlayout for use in the Controller.
*/
public CardLayout getCardLayout() { return cards; }


/**
*   Returns the current version of this updater as a double
*
*   @return     the version of this updater as a double.
*/
public double getUpdaterVersion() { return UPDATER_VERSION; }

/**
*   Returns a string that tells if the customer is useing windows or mac
*
*   @return     the operating system in use by the customer
*/
public static String getOSType() {
    String retString = "";
    String oST = System.getProperty("os.name").toLowerCase();
    int spacePos = oST.indexOf(" ");
    if (spacePos > 0) {
        retString = oST.substring(0, spacePos);
    }
    retString.trim();
    return retString;
}


/**
*   Returns the main root frame for display purposes in controller.java
*
*   @return JFrame  returns rootFrame.
*/
public JFrame getRootFrame() { return rootFrame; }

}

好的,记住这个类只是在后台执行一些实用程序的操作,并且可能不涉及除创建背景GUI和告知SelfUpdate卡片显示之外的任何事情。

最后,这是SelfUpdater.java文件,它显示带有进度条的SelfUpdater面板,并执行所有服务器查询,这很好地工作。请注意,我在downloadUpdate方法中(在控制器文件中调用)中有System.out.println调试语句,它们可以正常工作并在控制台中输出。那个方法中的selfUpdateProgress.setValue(int)和taskOutput.setText(txt)语句什么都没有做。此外,我在doInBackground中放置了一个println,在那里它设置setProgress(int),并且可以在控制台上正确打印,但进度条不更新。就是这样。

import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import javax.swing.*;
import java.io.*;
import java.net.*;
import java.util.zip.*;

// Create and start class
public class SelfUpdater extends JPanel {

// These are the variables needed for use in this class
private JPanel selfUpdatePanel;
private JProgressBar selfUpdateProgress;
private Task task;
private JTextArea taskOutput;
private Updater util;

/**
*   Default class constructor, instantiates variables and sets up GUI.
*
*
**/
public SelfUpdater() {
    // Progress Bar
    selfUpdateProgress = new JProgressBar(0, 100);
    selfUpdateProgress.setValue(0);
    selfUpdateProgress.setStringPainted(true);
    selfUpdateProgress.setPreferredSize(new Dimension(470,29));

    // Layout
    SpringLayout selfUpdateLayout = new SpringLayout();
    SpringLayout pBarLayout = new SpringLayout();


    // Font and color setup for Task Output
    Font myFont = new Font("Serif", Font.BOLD, 16);
    Color myColor = new Color(255, 170, 0);


    // Description of progress pane
    taskOutput = new JTextArea("Checking server for updates to the updater.", 1, 39);
    taskOutput.setFont(myFont);
    taskOutput.setForeground(myColor);
    taskOutput.setEditable(false);
    taskOutput.setOpaque(false); // this is false after setting up the window.

    //extras needed for the class workings
    util = new Updater();

    // Images for progress bar setup
    JLabel pBar = new JLabel(new ImageIcon(util.PROGBACK_IMAGE_PATH));
    pBar.setOpaque(false);
    //pBar.setLayout(pBarLayout);
    //pBar.add(taskOutput);
    //pBar.add(selfUpdateProgress);

    // Main panel
    selfUpdatePanel = new JPanel();
    selfUpdatePanel.setPreferredSize(new Dimension(800, 435));
    selfUpdatePanel.setLayout(selfUpdateLayout);
    selfUpdatePanel.setOpaque(false); 
    selfUpdatePanel.add(taskOutput);
    selfUpdatePanel.add(selfUpdateProgress);
    selfUpdatePanel.add(pBar);  

    // Constrain your bits.
    // First constrain PBar to the self update panel
    selfUpdateLayout.putConstraint(SpringLayout.SOUTH, pBar, -40, SpringLayout.SOUTH, selfUpdatePanel);
    selfUpdateLayout.putConstraint(SpringLayout.WEST, pBar, 150, SpringLayout.WEST, selfUpdatePanel);
    selfUpdateLayout.putConstraint(SpringLayout.SOUTH, taskOutput, -50, SpringLayout.SOUTH, selfUpdatePanel);
    selfUpdateLayout.putConstraint(SpringLayout.WEST, taskOutput, 175, SpringLayout.WEST, selfUpdatePanel);
    selfUpdateLayout.putConstraint(SpringLayout.SOUTH, selfUpdateProgress, -84, SpringLayout.SOUTH, selfUpdatePanel);
    selfUpdateLayout.putConstraint(SpringLayout.WEST, selfUpdateProgress, 171, SpringLayout.WEST, selfUpdatePanel); }

/**
*   Will return the jpanel that contains the gui elements for the Self-Update
*
*   @return JPanel  The Self-Update gui.
*
*/
public JPanel getSelfUpdatePanel() { return selfUpdatePanel; }

/**
*   This will check the server to see if an update is available for the updater
*
*   @return int     Returns an int that will describe the answer from the server.
*                   Possible Return values:
*                   0 = Problem checking for update: Server return NULL
*                   1 = Second type of problem checking for update: Server returned empty string
*                   2 = Update available.
*                   3 = Update not needed.
*
*/
public int checkForUpdate() {
    // ask the server what version it's updater is.
    String serverUpdaterVersion = "";

    try {

        HttpConnect conn = new HttpConnect();
        String urlRequest = util.URL_CONNECT + "action=get_updater&platform=" + util.getOSType();
        serverUpdaterVersion = conn.textRequest(urlRequest, 1);

    } catch (MalformedURLException e) {
        JOptionPane.showMessageDialog(null, "We were unable to connect to the server while checking for an updater update, please check your internet connection.", "Attention!",JOptionPane.ERROR_MESSAGE);            
    } catch (IOException e) {
        JOptionPane.showMessageDialog(null, "We were unable to open the connection to the server while checking for an updater update, please check your internet connection.", "Attention!",JOptionPane.ERROR_MESSAGE);        
    }

    // check for errors and return proper int.
    if (serverUpdaterVersion == null) { // There is an error if the server returns null, return 0
        return 0;
    } else if (serverUpdaterVersion.equals("")) { // if the server returns an empty string return 1 for an error
        return 1;
    } else { // not null or empty string. check versions
        // Check version of this updater to servers version
        double sVers = Double.parseDouble(serverUpdaterVersion);

        if((double)sVers == util.getUpdaterVersion()) { // return 3 if no update needed here.
            return 3;
        } else { // otherwise return 2 so we can get the update
            return 2;
        }

    }
}

/**
*   This will download the update from the server.
*
*   @return File        The downloaded file from the server. A zip file usually.
*
*/
public void downloadUpdate() {
    // turn on wait cursor
    util.getRootFrame().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

    // start a new task which does the download
    // Instances of javax.swing.SwingWorker are not reusuable, so
    // we create new instances as needed.
    task = new Task();
    // add a property listener to the task so it knows to update the progress meter.
    task.addPropertyChangeListener(new PropertyChangeListener() {
        @Override
        public void propertyChange(PropertyChangeEvent evt) {

            switch(evt.getPropertyName()) {
                case "progress":// set the progress value and the task output value.
                    selfUpdateProgress.setIndeterminate(false);
                    int prg = (Integer) evt.getNewValue();
                    selfUpdateProgress.setValue(prg);
                    taskOutput.setText("Downloading and unzipping update. Progress = " + prg + "%");
                    System.out.println("Percent progress: " + prg + "%");
                    break;
            }
        }
    });
    // execute or start the task.
    task.execute();
}

/**
*   This method will unzip the downloaded file, and start the installation.
*   Then it will close this program while the installation completes.
*
*
*/
public void unzipNewUpdater() {
    // create strings for naming the zip file to open up and where to put it.
    String zipFile = "NewUpdater.zip";
    String outputFolder = System.getenv("SystemDrive") + "\\DynastyAddons";
    // Try the unzipping and catch any errors.
    try {

        // Setup the input stream and get the entry ready to unzip.
        ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile));
        ZipEntry ze = zis.getNextEntry();

        // loop to open each entry and output it to the output folder and file.
        while(ze!=null) {
            // Get the name
            String entryName = ze.getName();

            // get the file to unzip
            File f = new File(outputFolder + File.separator + entryName);

            // Create folders needed to hold the unzipped stuff
            f.getParentFile().mkdirs();

            // get output stream setup to copy the file to from the zip
            FileOutputStream fos = new FileOutputStream(f);

            // get length of file to make sure we get the whole thing moved
            int len;
            byte buffer[] = new byte[1024];

            // loop thru the entry writing the whole file to the output directory
            while((len = zis.read(buffer)) > 0){
                fos.write(buffer, 0, len);
            }

            // close the output stream and get the next entry ready for the next iteration of the loop.
            fos.close();
            ze = zis.getNextEntry();

        }

        // close the entry and input stream since we're done.
        zis.closeEntry();
        zis.close();

    } catch (FileNotFoundException ex) {
        // throw error
    } catch (IOException ex) {
        // throw error
    }
}

// This private class handles the download and unzip of the new updater if needed.
class Task extends SwingWorker<Void, Void> {


    @Override
    public Void doInBackground() {
        try {
            HttpConnect conn = new HttpConnect();
            String downloadURL = util.URL_CONNECT + "action=download_updater&platform=" + util.getOSType();
            conn.downloadFile(downloadURL);

            InputStream inputStream = conn.getInputStream();

            FileOutputStream outputStream = new FileOutputStream(System.getenv("SystemDrive") + "\\DynastyAddons\\NewUpdater.zip");

            byte[] buffer = new byte[util.BUFFER_SIZE];
            int bytesRead = -1;
            long totalBytesRead = 0;
            int percentCompleted = 0;
            long fileSize = conn.getContentLength();

            taskOutput.setText("Downloading Newest Updater.");
            //setProgress(0);

            while ((bytesRead = inputStream.read(buffer)) != -1) {

                outputStream.write(buffer, 0, bytesRead);
                totalBytesRead += bytesRead;
                percentCompleted = (int) (totalBytesRead * 100 / fileSize);
                setProgress(percentCompleted);

            }

            outputStream.close();
            conn.disconnect();

        } catch (IOException ex) {
            JOptionPane.showMessageDialog(util.getRootFrame(), "Error downloading Updater file. Please send this entire error to support@dynastyaddons.com. \n Error: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
            setProgress(0);
        }
        return null;
    }

    @Override
    public void done() {
        // Create msg window saying update downloaded.
        JOptionPane.showMessageDialog(util.getRootFrame(), "The new updater has been downloaded. \nClick OK to close this updater and start the installation of the new version.", "Attention", JOptionPane.PLAIN_MESSAGE);

        // Unzip the updater
        unzipNewUpdater();

        // Tell the cursor we're not busy anymore
        setProgress(100);
        selfUpdateProgress.setValue(100);
        taskOutput.setText("Done Downloading New Updater. Installing...");
        util.getRootFrame().setCursor(null);

        // Create command used to open the udpater installer.
        String cmd = "cmd /c " + System.getenv("SystemDrive") + "\\DynastyAddons\\InstallDynastyAddonsUpdater.exe";

        // Here is where we run the exe that will install the new updater.
        try{
            Runtime.getRuntime().exec(cmd);
        }catch (FileNotFoundException ex){
            // handle this error
        }catch (IOException ex) {
            // handle this error
        }

        // Now close this updater so the new one can install.
        System.exit(0);
    }
}

}

希望代码能够正常编译,如果需要查看其工作情况,请告知我,我将更新内容以使其在编译中正常工作。所以我试了许多方法,使SelfUpdater类实现PropertyChangeListener并实现PropertyChange(event),我尝试将JProgressBar馈送到Task类的构造函数中。我尝试在SwingWorker中输出整数并使用Publish和Process来更新taskOutput和JProgressBar,我尝试重新编写整个类来修复代码并使其更容易找出问题。使用教程和一些我的代码进行测试(它们表现得很好),但每次我回到这里的更新程序代码时,该进度条都无法更新。我真的希望有人能给我一点见解,以便我可以完成这个项目并开始做一些新的事情!这是我必须解决的最后一件事(除非在Mac上存在问题),然后我就可以回到测试并将其分发给我们的客户了。
欢迎对代码的任何部分进行评论(我可能做了一些愚蠢的事情)。我总是寻找对我的代码的批评,特别是如果我没有按照良好的设计执行某些操作。如果需要更多信息,我可以轻松地粘贴组成此更新程序的七个类中的所有代码。
所有内容都已编译,并且工作正常,除了这个JProgressBar不会显示进度,尽管我可以在控制台上输出它。提前感谢您的回答,对于这篇迷你小说,非常抱歉,我还没有问过问题,并且一直能够从其他人的问题和答案中找到答案,现在我已经被卡住了,准备完成这个项目!:D
如果我在发布帖子时出现问题,请提前谅解,记住这是我第一次发布帖子,虽然我已经阅读了成百上千的帖子,但我确信我的新手错误已经搞砸了一些东西,因此请随意责骂我,并指出我的错误以便我进行修正。:)
编辑:更新了selfUpdater.java以反映仅使用一个Spring布局。

Runtime.getRuntime().exec(cmd); 在完成中执行???嗯,例如:https://dev59.com/eVfUa4cB1Zd3GeqPI4dE#6114890,并使用get()在完成中:https://dev59.com/COo6XIcBkEYKwwoYSClJ - mKorbel
如果我理解正确,done() 方法中的 get() 将返回已下载的文件。但是,我是否仍然需要执行某种 Runtime.exec 来运行从下载的 zip 中提取出来的 exe? - Jason Langois
doInBackground() 是调用 Runtime.exec 的正确位置,SwingWorker 中实现的其余方法都是 EDT 连接器,所有操作都在 EDT 上完成,然后 Swing GUI 会冻结或无响应到键盘/鼠标事件直到 Runtime.exec 结束,你确定你熟悉 Swing 中的单线程(EDT)吗? - mKorbel
是的,实际上需要发生的是exe是更新的Updater程序的安装程序。runtime.exec启动该安装程序,然后立即关闭此更新程序的实例,以便可以安装新的Jar而不会出现正在使用的文件复制问题。这就是为什么我在done()中完成它,因为它需要在调用exec之后立即System.exit(0)。 :) - Jason Langois
1
将done()视为终点站,所有操作和/或准备工作应在下一次使用之前完成。 - mKorbel
显示剩余3条评论
2个回答

4
你遇到的是布局问题,与 SwingWorker 无关。 JProgressBar 正在更新,只是你看不到它。
请检查你的主方法。你创建了两个 SelfUpdater 的实例,将一个添加到 GUI 中并更新另一个。
public static void main(String[] args) {
    util = new Updater(); // <-- don't do this, it calls Swing code from a thread that is not EDT
    // Schedule a job for the event dispatch thread.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {

            // setup a new GUI
            util.createGUI(); // <-- creates an instance of SelfUpdater and adds it to GUI
            JFrame rFrame = util.getRootFrame();                
            JPanel gFrame = util.getCardLayoutFrame();
            CardLayout cards = (CardLayout) gFrame.getLayout();
            cards.show(gFrame, "UpdateUpdaterPanel");

            rFrame.pack();
            rFrame.setLocationRelativeTo(null);
            rFrame.setVisible(true);

            SelfUpdater selfUp = new SelfUpdater(); // <-- creates another instance             
            int needUpdate = selfUp.checkForUpdate();                                       
            if (needUpdate == 2) {// Update available for download. Download it.
                selfUp.downloadUpdate();

            } 


        }
    });

}

如果组件没有添加到任何位置,就不能期望它们被显示出来。 :)

我不确定我是否理解得很清楚。我在这里创建了面板,并将其添加到更新程序中的主面板中,该面板使用CardLayout。我编译了它,虽然没有错误,但也没有显示进度条。看起来您抹掉了进度条的布局以及进度条所在的主要jpanel的布局。所以您是说我应该更改进度条显示的布局和发送到更新程序的主面板的布局,以便放置在CardLayout上?还是只需忘记pbar图像的布局,只需将进度条添加到发送到更新程序的主面板中即可? - Jason Langois
好的,我尝试了你说的。我将JProgressBar发送到更新程序文件中,该文件将其附加到具有边框布局的普通JPanel上。然后,该面板被用作cardlayout中的UpdaterUpdatePanel。进度条占据了整个空间(这不是一个大的青色,只是作为测试),并且像往常一样在控制台中打印出进度,但是这次进度条没有发生任何变化。它始终保持在0%,从未改变过。我将其切换回来,但这次剪切了一个springlayouts,并且只在发送的主面板上有一个springlayouts。 - Jason Langois
先生,您是正确的,我误导了您。我会编辑我的回答。 - predi
太好了!非常感谢你,Predi。我已经接受了你的答案并点赞了。我真的很感激你的帮助,现在它像魔法一样运行得很好,因为我将selfupdater对象从更新器传递到控制器,而不是创建另一个实例!我应该用正确的代码更新问题,还是只接受你的答案就可以了? - Jason Langois

0

我有一个问题,实际的方法是有效的,但 setProgress 部分似乎不起作用。从我设置的 println 中判断,它们应该都正常工作,所以我认为 Predi 的答案是正确的,只需要理解一下。除此之外,它从来没有更新过进度条,始终停留在 0%。 - Jason Langois
1
这正是SwingWorker所做的,它在单独的线程中运行,并内置了线程安全功能... - MadProgrammer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接