使用属性更改侦听器来更新swing组件

时间:2018-05-27 20:18:05

标签: java swing swingworker propertychangelistener

我第一次使用属性更改侦听器,所以我对它在几个类之间的使用方式不太熟悉。
我在java中编写了一个下载管理器,在类下载有downloadSize和sizeOfFile等字段。还有类DownloadPanel,它是一个GUI,是一个jpanel,包含一个JProgressbar和几个JLabel来显示文件的数量。下载或文件大小(使用下载字段) Download类扩展了SwingWorker并使用HttpURLConnection从特定URL下载给定文件 在下载文件以更新其下载面板时,我已经实现了属性更改侦听器。问题是JProgressbar正在正确更新,但JLabel显示的downloadsSize和sizeOfFile不会通过下载文件来改变。

请注意,类中不相关的部分和getter / setter被省略,只包含与问题相关的部分。

Property Change Listener的实现:

public class DownloadPanelPropertyListener implements PropertyChangeListener {

    Download download;

    public DownloadPanelPropertyListener(Download download) {
        this.download = download;
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        if ("progress".equals(evt.getPropertyName()))
            download.getDownloadPanel().getJpb().setValue((Integer) evt.getNewValue());
        else if ("downloadPanel".equals(evt.getPropertyName())) {
            DownloadPanel temp = (DownloadPanel) evt.getNewValue();
            int ds = temp.download.getDownloadedSize();
            int sof = temp.download.getSizeOfFile();
            download.getDownloadPanel().setDownloadedSizeLabel(ds, sof);
        }
    } 

DownloadPanel类代码:

public class DownloadPanel extends JPanel {

    Download download;
    JProgressBar jpb = new JProgressBar(0,100);
    JLabel downloadSpeedLabel;
    JLabel downloadedSizeLabel;

    public DownloadPanel (Download d) {
        download = d;
        this.addPropertyChangeListener("downloadPanel",new DownloadPanelPropertyListener(download));
        jpb.setValue( (int) (( (double) download.getDownloadedSize() / (double) download.getSizeOfFile()) * 100)) ;
        jpb.setBounds(100,25,400,10);
        jpb.setIndeterminate(false);
        JLabel progressBarValue = new JLabel("%" + jpb.getValue() + "");
        progressBarValue.setBounds(510,18,25,20);
        add(progressBarValue);
        downloadSpeedLabel = new JLabel (String.format ("%dKbs",download.getDownloadSpeed()));
        downloadedSizeLabel = new JLabel (String.format ("%d MG / %d MG",download.getDownloadedSize(),download.getSizeOfFile()));
        add(downloadSpeedLabel); add(downloadedSizeLabel);
    }  

和课程下载:

public class Download extends SwingWorker<Void,Void> implements Serializable,Runnable {

    private transient DownloadPanel downloadPanel = null;
    private transient MainPage mp;
    private String fileName;
    private String hostName;
    private int downloadSpeed;
    private int downloadedSize;
    private int sizeOfFile;
    private int queueIndex;
    private URL url;

    public Download (MainPage c,URL url,File f,int index) {

        addPropertyChangeListener(new DownloadPanelPropertyListener(this));
        mp = c;
        this.url = url;
        queueIndex = index;
        downloadTime = time;
        fileName = url.getFile();
        hostName = url.getHost();
        sizeOfFile = -1;
        downloadSpeed = 0;
        downloadedSize = 0;
    }

    public Void doInBackground () {
        RandomAccessFile file = null;
        InputStream stream = null;

        try {
            // Open connection to URL.
            HttpURLConnection connection =
                    (HttpURLConnection) url.openConnection();

            // Specify what portion of file to download.
            connection.setRequestProperty("Range",
                    "bytes=" + downloadedSize + "-");

            // Connect to server.
            connection.connect();

            // Make sure response code is in the 200 range.
            if (connection.getResponseCode() / 100 != 2) {
                System.out.println("0");
            }

            // Check for valid content length.
            int contentLength = connection.getContentLength();
            if (contentLength < 1) {
                System.out.println("1");
            }

      /* Set the size for this download if it
         hasn't been already set. */
            if (sizeOfFile == -1) {
                sizeOfFile = contentLength;
            }

            // Open file and seek to the end of it.
            file = new RandomAccessFile(new File(s.getCurrentDirectory(),getFileName(url)),
                    "rw");
            file.seek(downloadedSize);

            stream = connection.getInputStream();
            while (status == CURRENT) {
        /* Size buffer according to how much of the
           file is left to download. */
                byte buffer[];
                if (sizeOfFile - downloadedSize > MAX_BUFFER_SIZE) {
                    buffer = new byte[MAX_BUFFER_SIZE];
                } else {
                    buffer = new byte[sizeOfFile - downloadedSize];
                }

                // Read from server into buffer.
                int read = stream.read(buffer);
                if (read == -1)
                    break;

                // Write buffer to file.
                file.write(buffer, 0, read);
                downloadedSize += read;
                setProgress ( (int) (( (double) getDownloadedSize() / (double) getSizeOfFile()) * 100));
            }

      /* Change status to complete if this point was
         reached because downloading has finished. */
            if (status == CURRENT) {
                status = COMPLETE;
            }
        } catch (Exception e) {
            System.out.println("2");
            e.printStackTrace();
        } finally {
            // Close file.
            if (file != null) {
                try {
                    file.close();
                } catch (Exception e) {}
            }

            // Close connection to server.
            if (stream != null) {
                try {
                    stream.close();
                } catch (Exception e) {}
            }
        }
        return null;
    }

    private String getFileName(URL url) {
        String fileName = url.getFile();
        return fileName.substring(fileName.lastIndexOf('/') + 1);
    }

1 个答案:

答案 0 :(得分:2)

我没有看到你在你的财产变更监听器中设置了JLabel的文本,但是说过,你不应该这样做,因为它违反了OOP封装。更确切地说:

  • DownloadPanel课程提供public void setPercentDownload(int value)方法,并在此方法中,通过setText(...) 和 JLabel的文字LI>
  • 在Prop更改侦听器中,调用此方法将值传递给GUI。
  • 不要在聆听者中设置进度条的值,让视图执行此操作,如上所述。
  • 请务必在道具更改侦听器中侦听newValue == SwingWorker.StateValue.DONE。发生这种情况时,请在您的worker上调用get(),以便捕获后台线程中可能发生的任何异常。
  • 附带问题:只说'#34;否&#34;到null布局和setBounds。它们使得僵硬的GUI不能在所有平台上运行,并且是一个可以调试和增强的熊。使用布局管理器。

例如,我的Minimal, Complete, and Verifiable example(MCVE):

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.beans.*;
import java.io.Serializable;
import java.util.concurrent.ExecutionException;

import javax.swing.*;

public class FooProgress  {
    private static void createAndShowGui() {
        JFrame frame = new JFrame("FooProgress");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new DownloadPanel());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

class DownloadListener implements PropertyChangeListener {
    private DownloadPanel downloadPanel;

    public DownloadListener(DownloadPanel downloadPanel) {
        this.downloadPanel = downloadPanel;
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        if ("progress".equals(evt.getPropertyName())) {
            int value = (int) evt.getNewValue();
            downloadPanel.setPercentDownload(value);
        } else if ("state".equals(evt.getPropertyName())) {
            if (evt.getNewValue() == SwingWorker.StateValue.DONE) {
                Download download = (Download) evt.getSource();
                try {
                    download.get();
                } catch (InterruptedException | ExecutionException e) {
                    // TODO: handle exceptions here
                    e.printStackTrace();
                }
            }
        }
    }
}

@SuppressWarnings("serial")
class DownloadPanel extends JPanel {
    private static final String PROGRESS_FORMAT = "%03d%%";
    private JProgressBar jpb = new JProgressBar(0, 100);
    private JLabel downloadedSizeLabel = new JLabel(String.format(PROGRESS_FORMAT, 0));
    private DownLoadAction downLoadAction = new DownLoadAction();

    public DownloadPanel() {
        JPanel topPanel = new JPanel();
        topPanel.add(new JLabel("Download Progress:"));
        topPanel.add(downloadedSizeLabel);
        JPanel bottomPanel = new JPanel();
        bottomPanel.add(new JButton(downLoadAction));

        setLayout(new BorderLayout());        
        add(topPanel, BorderLayout.PAGE_START);
        add(jpb);
        add(bottomPanel, BorderLayout.PAGE_END);
    }

    public void setPercentDownload(int value) {
        downloadedSizeLabel.setText(String.format(PROGRESS_FORMAT, value));
        jpb.setValue(value);
        if (value == 100) {
            downLoadAction.setEnabled(true);
        }
    }

    private class DownLoadAction extends AbstractAction {
        public DownLoadAction() {
            super("Download");
            putValue(MNEMONIC_KEY, KeyEvent.VK_D);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            setEnabled(false);
            setPercentDownload(0);
            Download download = new Download();
            DownloadListener listener = new DownloadListener(DownloadPanel.this);
            download.addPropertyChangeListener(listener);
            download.execute();
        }
    }
}

class Download extends SwingWorker<Void, Void> implements Serializable, Runnable {

    private static final long SLEEP_TIME = 200;

    public Void doInBackground() throws Exception {
        int myProgress = 0;
        while (myProgress < 100) {
            myProgress += (int) (10 * Math.random());
            myProgress = Math.min(myProgress, 100);
            setProgress(myProgress);
            Thread.sleep(SLEEP_TIME);
        }
        return null;
    }

}

将来,您希望使用您的代码创建和发布MCVE,以便我们可以毫不费力地编译,运行和测试它。你的代码中有太多的文件处理,我们目前无法测试。我已经用90%的代码替换了Thread.sleep。