swing快速入门(三十八)进度条

注释很详细,直接上代码

上一篇

新增内容
1.进度条的创建(水平or垂直)
2.使用多线程模拟耗时操作以免阻塞主线程
3.进度条属性设置
4.复选框状态改变监听器
5. 使用定时器任务定时读取更新进度条
6.进度条变化监听器
7.定时器的适时关闭条件
8.volatile声明的的作用
9.多线程执行睡眠方法

源码:

package swing31_40;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class swing_test_36 {

    //创建一个窗口
    JFrame jFrame = new JFrame("测试进度条");

    //创建一个水平的进度条
    JProgressBar bar = new JProgressBar(JProgressBar.HORIZONTAL);

    //创建一个不确定进度的复选框
    JCheckBox indeterminate = new JCheckBox("不确定进度");

    //创建一个不绘制边框的复选框
    JCheckBox noBorder = new JCheckBox("不绘制边框");

    //初始化方法
    public void init(){

        //创建一个垂直的Box
        Box box = new Box(BoxLayout.Y_AXIS);
        //添加复选框
        box.add(indeterminate);
        //添加复选框
        box.add(noBorder);

        //设置jFrame窗口的布局
        jFrame.setLayout(new FlowLayout());

        //添加box
        jFrame.add(box);

        //把进度条添加到jFrame窗口中
        jFrame.add(bar);

       //使用新线程
        SimulatedActivity simulatedActivity = new SimulatedActivity(100);
        new Thread(simulatedActivity).start();

        //设置进度条属性:
        //设置进度条的最小值和最大值
        bar.setMinimum(0);
        bar.setMaximum(simulatedActivity.getAmount());

        //设置进度条中绘制完成百分比
        bar.setStringPainted(true);

        //根据选择决定是否绘制进度条边框
        noBorder.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
             //获取复选框的状态
                boolean flag = noBorder.isSelected();
                 //设置进度条是否有边框
                bar.setBorderPainted(!flag);
            }
        });

        //根据选择决定是否是不确定进度条
        indeterminate.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //获取复选框的状态
                boolean flag = indeterminate.isSelected();

                //设置进度条的不确定状态
                //不确定状态即只有运动状态而不显示进度样式
                bar.setIndeterminate(flag);

                //是否绘制百分比
                bar.setStringPainted(!flag);//如果修改成了不确定状态,那么就不绘制百分比
            }
        });

        设置窗口的默认关闭操作
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //设置窗口的大小
        jFrame.pack();
        //设置窗口可见
        jFrame.setVisible(true);

        //通过定时器,间隔一定时读取一次simulatedActivity中的current值,更新进度条的进度
        Timer timer = new Timer(300, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //设置当前进度
                bar.setValue(simulatedActivity.getCurrent());
            }
        });

        //启动定时器
        timer.start();

        //监听进度条的变化,如果进度完成为100%,那么停止定时器
        bar.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {//监听进度条的变化

                //如果进度完成为100%,那么停止定时器
                //否则定时器会一直占用资源
                if (bar.getValue()==bar.getMaximum()){
                    //停止定时器
                    timer.stop();
                }
            }
        });


    }

    public static void main(String[] args) {

        //创建测试对象
        new swing_test_36().init();
    }

    //定义一个线程任务,模拟耗时操作
    private class SimulatedActivity implements Runnable{

        //volatile 关键字用于在多线程环境下保证变量的可见性,
        // 禁止指令重排序,确保变量的更新能够立即更新到主内存中,
        // 而不需要再调用volatile变量的线程进行额外的同步或者赋值操作。
        // 这可以避免一些并发问题,如不可见性和不一致性

        //当前值(变量为内存可见)
        //虽然这里不用这玩意也行
        //(因为每次使用这个值都是调用公共方法重新获取到current的值)
        //但是建议使用以避免后期添加功能时不会有并发性问题
        private volatile int current = 0;

        //最大值
        private int amount;

        //构造方法
        public SimulatedActivity(int amount) {
            this.amount = amount;
        }

        //获取当前值
        public int getCurrent() {
            return current;
        }

        //设置当前值
        public void setCurrent(int current) {
            this.current = current;
        }

        //获取最大值
        public int getAmount() {
            return amount;
        }

        //设置最大值
        public void setAmount(int amount) {
            this.amount = amount;
        }

        //重写run方法
        @Override
        public void run() {

            //通过循环,不断地修改current的值,模拟任务完成量
            //这里需要注意是到了对应的条件才能停止循环,如果只是一次操作则会只执行一次
            while(current<amount){
                try {

                    //睡眠500毫秒(在多线程环境下执行不会阻塞主线程)
                    Thread.sleep(500);

                } catch (InterruptedException e) {//捕获异常
                    //打印异常信息
                    e.printStackTrace();
                }

                //增加当前值
                current++;
            }
        }
    }
}

运行效果:

swing快速入门(三十八)进度条_第1张图片

swing快速入门(三十八)进度条_第2张图片

swing快速入门(三十八)进度条_第3张图片
swing快速入门(三十八)进度条_第4张图片
下一篇

你可能感兴趣的:(#,Swing,java,swing)