🐧注释很详细,直接上代码
🐼源码:
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++;
}
}
}
}
🐲运行效果: