Swing进度条应用—文件传输进度展示

目录

GIF演示

 代码


 

此示例涵盖的知识点:线程、IO流、File、Swing、Listener、JFrame、JFileDialog、JOptionPane、JProgressBar、Timer

GIF演示

58db9deb466f4092afd9d07721838740.gif

 代码

package psn.exer.progress;

import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.util.UUID;

/**
 * on 2023/3/4 21:20
 */
public class FileTrans {
    public static void main(String[] args) {
        new FileTrans().init();
    }

    public void init() {
        JFrame jf = new JFrame();
        JButton btn = new JButton("传输文件");
        FileDialog fld = new FileDialog(jf, "请选择需要传输的文件", FileDialog.LOAD);
        FileDialog fsd = new FileDialog(jf, "请选择文件保存的位置", FileDialog.SAVE);
        fld.setBounds(400, 200, 400, 300);
        fsd.setBounds(400, 200, 400, 300);
        jf.add(btn, BorderLayout.NORTH);
        btn.addActionListener(e -> {
            //暂时禁用按钮,防止多次点击按钮并进行多次文件传输,造成界面上多个进度条频繁切换
            btn.setEnabled(false);
            //开始选择文件,并将其信息传递给进度条和文件传输线程
            fld.setVisible(true);
            if (fld.getFile() == null || fld.getFile() == "") {
                JOptionPane.showConfirmDialog(jf, "请选择需要传输的文件!", "未选择文件", JOptionPane.CLOSED_OPTION);
                btn.setEnabled(true);
                return;
            }
            //选择文件保存位置,设置文件名
            JOptionPane.showConfirmDialog(jf, "请选择文件保存的位置", "提示信息", JOptionPane.CLOSED_OPTION);
            fsd.setVisible(true);
            if (fsd.getFile() == null || fsd.getFile() == "") {
                JOptionPane.showConfirmDialog(jf, "请输入文件名", "未输入文件名", JOptionPane.CLOSED_OPTION);
                btn.setEnabled(true);
                return;
            }
            //创建文件传输任务
            FileTransTask task = new FileTransTask(
                    new File(fld.getDirectory(), fld.getFile()),
                    new File(fsd.getDirectory(), fsd.getFile() + fld.getFile().substring(fld.getFile().lastIndexOf("."))),
                    1024);
            //创建进度条,设置其外观:完成部分颜色、边框、完成百分比及字体
            JProgressBar pb = new JProgressBar(JProgressBar.HORIZONTAL, 0, task.getTotal());
            pb.setForeground(new Color(73, 156, 84));
            pb.setBorderPainted(true);
            pb.setStringPainted(true);
            pb.setFont(new Font("等线", Font.ITALIC, 18));
            jf.add(pb, BorderLayout.SOUTH);
            //使进度条呈现
            jf.validate();
            //将文件传输任务交由此线程执行
            Thread ft = new Thread(task, "file-trans");
            ft.start();
            //创建定时监听线程timer,其任务是每隔1毫秒获取传输完成量,然后更新进度条的值
            Timer timer = new Timer(1, e1 -> pb.setValue(task.getFinished()));
            timer.start();
            //给进度条注册改变监听器,文件上传任务结束后,立即结束timer线程,提示用户操作成功,进度条不可见并移除进度条,开启上传按钮
            pb.addChangeListener(e2 -> {
                if (task.getFinished() >= pb.getMaximum()) {
                    timer.stop();
                    JOptionPane.showConfirmDialog(jf, "文件传输完毕!", "操作成功", JOptionPane.CLOSED_OPTION);
                    pb.setVisible(false);
                    jf.remove(pb);
                    btn.setEnabled(true);
                }
            });
        });
        //窗口基本设置
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.setTitle("实现真实文件的传输");
        jf.setBounds(400, 200, 400, 300);
        jf.setVisible(true);
    }
}

class FileTransTask implements Runnable {
    private int bufferSize;//缓冲区字节数
    private int total;//文件总字节数
    private volatile int finished;//传输完成字节数
    private File originFile;//源文件
    private File destFile;//目标文件(另存为的文件)

    public int getFinished() {
        return finished;
    }

    public int getTotal() {
        return total;
    }

    /**
     * @param originFile 源文件
     * @param destFile   另存为的文件
     * @param bufferSize 文件传输缓存区大小
     */
    public FileTransTask(File originFile, File destFile, int bufferSize) {
        this.bufferSize = bufferSize;
        this.originFile = originFile;
        this.destFile = destFile;
        if (originFile != null) {
            this.total = (int) originFile.length();
        }
        finished = 0;
    }

    @Override
    public void run() {
        try {
            FileInputStream fis = new FileInputStream(this.originFile);
            FileOutputStream fos = new FileOutputStream(this.destFile);
            byte[] buf = new byte[this.bufferSize];
            //开始边读边存文件
            while (true) {
                fis.read(buf);
                if ((total - finished) <= bufferSize) {//一次就传输完毕或者分多次传输的最后一次
                    fos.write(buf, 0, total - finished);
                    finished = total;//结束传输的条件
                    break;
                } else {
                    finished += bufferSize;
                    fos.write(buf);
                }
                Thread.sleep(100);//增加文件传输耗时
            }
            fos.close();
            fis.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

 

 

 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
swing进度条是一种可以动态更新的组件,它可以在长时间运行的任务中提供可视化的进度表示。通过适当的处理,我们可以实现进度条的实时更新。 首先,我们需要创建一个JProgressBar对象,并设置其最小值和最大值,以定义进度条的范围。然后,我们可以将进度条添加到要显示的界面中。 接下来,我们需要创建一个长时间运行的任务。这个任务可以是任何你想要执行的操作,比如文件下载、数据处理等。在任务执行期间,我们可以根据进度更新进度条的值。 为了实现进度条的动态更新,我们可以在任务的主循环中使用Swing的Event Dispatch Thread(EDT)来更新进度条的值。在每次更新进度时,我们可以调用进度条对象的setValue()方法,将新的进度值传递给它。由于EDT是Swing的事件处理线程,它能够确保在图形界面更新之前完成任务。 另外,为了确保进度条的动态更新能够顺利进行,我们还需要注意以下几点: 1. 避免在EDT中执行长时间运行的任务,以免阻塞用户界面。可以将任务放在一个单独的线程中执行,并使用SwingUtilities.invokeLater()方法在EDT中更新进度条的值。 2. 在任务执行期间,需要适时调用Thread.sleep()方法,以使任务执行稍微放慢,从而有足够时间更新进度条的值。 3. 如果任务过于繁重,可能会导致UI的卡顿。为了避免这种情况,可以考虑使用SwingWorker类来执行任务,并在其后台线程中适时调用publish()和process()方法更新进度条。 总之,通过合理的处理和使用Swing的EDT机制,我们可以实现swing进度条的动态更新,提供更好的用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bitDesigner

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值