использование слушателя изменения свойства для обновления компонентов свинга - PullRequest
0 голосов
/ 27 мая 2018

Я впервые использую прослушиватель изменения свойств, поэтому я не совсем знаком с тем, как его следует использовать между несколькими классами.
Я пишу менеджер загрузок в java, в классе Download thereэто такие поля, как downloadSize и sizeOfFile и т. д. Также существует класс DownloadPanel, который представляет собой графический интерфейс пользователя и является jpanel и содержит JProgressbar и несколько JLabels для отображения количества загружаемого файла или размера файла (используя поля загрузки).
класс Download расширяет SwingWorker и загружает данный файл с определенного URL-адреса с помощью HttpURLConnection.
при загрузке файла для обновления его панели загрузки я реализовал прослушиватель изменения свойств.проблема в том, что JProgressbar обновляется корректно, но JLabel, показывающий загруженные размеры и 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);
    }  

и класса Download:

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 голосов
/ 27 мая 2018

Я не вижу, чтобы вы когда-либо устанавливали текст JLabel в слушателе изменения свойств, но, сказав это, вы не должны этого делать, поскольку это нарушает инкапсуляцию ООП.Скорее:

  • Дайте вашему DownloadPanel классу метод public void setPercentDownload(int value), и в этом методе установите JProgressBar и текст JLabel с помощью setText(...)
  • В слушателе изменений Prop, вызовите этот метод, передав значение в GUI.
  • Не устанавливайте значение индикатора выполнения в слушателе, позвольте представлению делать это, как я уже отмечал выше.
  • Обязательно прослушайте newValue == SwingWorker.StateValue.DONE в вашем прослушивателе смены реквизита.Когда это происходит, вызовите get() на своем рабочем месте, чтобы вы могли перехватывать любые исключения, которые могли произойти в фоновом потоке.
  • Побочная проблема: просто скажите «нет» null раскладкам и setBounds.Они предназначены для жестких графических интерфейсов, которые не работают на всех платформах и являются медведем для отладки и улучшения.Используйте менеджеры компоновки.

Например, мой Пример минимального, полного и проверяемого (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% этого кода.

...