繁体   English   中英

使用属性更改侦听器更新挥杆组件

[英]using property change listener to update swing components

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

请注意,省略了类中无关的部分和获取/设置器,而只包括了与问题相关的部分。

属性更改侦听器的实现:

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);
    }

我看不到您曾经在属性更改侦听器中设置JLabel的文本,但是话虽如此,您不应该这样做,因为它违反了OOP封装。 而是:

  • 给您的DownloadPanel类提供一个public void setPercentDownload(int value)方法,在此方法中,通过setText(...)设置JProgressBar JLabel的文本
  • 在属性更改侦听器中,调用此方法,将值传递给GUI。
  • 请勿在侦听器中设置进度栏的值,而让视图执行此操作(如上所述)。
  • 确保在属性更改侦听器中侦听newValue == SwingWorker.StateValue.DONE。 发生这种情况时,请在工作线程上调用get() ,以便可以捕获后台线程中可能发生的任何异常。
  • 附带问题:对null布局和setBounds只需说“否”。 它们使刚性GUI不能在所有平台上运行,并且是调试和增强的负担。 使用布局管理器。

例如,我的最小,完整和可验证的示例 (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,以便我们实际上可以毫无困难地进行编译,运行和测试。 您的代码中包含过多的文件处理,我们目前无法测试。 我已将Thread.sleep替换为该代码的90%。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM