package com.fine.component.popup; import com.fine.theme.utils.FineUIScale; import com.formdev.flatlaf.util.ScaledEmptyBorder; import com.fr.concurrent.NamedThreadFactory; import com.fr.design.locale.impl.SupportLocaleImpl; import com.fr.design.ui.util.UIUtil; import com.fr.design.utils.DesignUtils; import com.fr.general.FRFont; import com.fr.general.locale.LocaleCenter; import javax.swing.JLabel; import javax.swing.JProgressBar; import javax.swing.plaf.ColorUIResource; import java.awt.BorderLayout; import java.awt.Font; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import static com.fine.swing.ui.layout.Layouts.cell; import static com.fine.swing.ui.layout.Layouts.column; import static com.fine.swing.ui.layout.Layouts.flex; import static com.fine.swing.ui.layout.Layouts.row; import static com.fine.theme.utils.FineUIScale.scale; /** * 进度条遮罩组件 * * @author Levy.Xie * @since 11.0 * Created on 2024/12/13 */ public class ProgressChild extends GlassPaneChild { private int progress; protected JLabel text; protected JProgressBar progressBar; private int step = 10; private static final int STEP_HEARTBEAT = 40; private static final int FONT_RGB = 333334; private static final int FONT_SIZE = 14; private static final String FONT_NAME = "Dialog"; public ProgressChild(String text) { this(text, DesignUtils.getDefaultGUIFont() .applySize(scale(FONT_SIZE)) .applyForeground(new ColorUIResource(FONT_RGB))); } public ProgressChild(String text, Font font) { initComponents(text, font); initLayout(); initScheduler(); } private void initComponents(String text, Font font) { this.text = new JLabel(text); this.text.setFont(font); //由于默认值的字体不支持韩文,所以要对韩文单独生成字体 LocaleCenter.buildAction(() -> { FRFont frFont = FRFont.getInstance().applySize(FONT_SIZE) .applyForeground(new ColorUIResource(FONT_RGB)).applyName(FONT_NAME); this.text.setFont(frFont); }, SupportLocaleImpl.SUPPORT_KOREA); this.progressBar = new JProgressBar(); progressBar.setBorderPainted(false); progressBar.setOpaque(false); progressBar.setBorder(null); progressBar.setMaximum(1000); } /** * 设置进度条最大加载时间,单位为s * * @param maxWait 最大等待时间 * @return 进度条遮罩层 */ public ProgressChild setMaxWait(int maxWait) { this.step = progressBar.getMaximum() * STEP_HEARTBEAT / (maxWait * 1000); return this; } /** * 设置进度条为不确定模式、无限加载 * */ public ProgressChild asIndeterminate() { progressBar.setIndeterminate(true); return this; } private void initLayout() { setLayout(new BorderLayout()); setPreferredSize(FineUIScale.createScaleDimension(400, 100)); add(column(10, cell(progressBar).weight(1), row(flex(), cell(text), flex()).weight(1.5) ).with(it -> it.setBorder(new ScaledEmptyBorder(30, 30, 20, 30))).getComponent(), BorderLayout.CENTER); } private void initScheduler() { final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1, new NamedThreadFactory(getClass().getSimpleName())); scheduler.scheduleWithFixedDelay(() -> { if (isComplete() && !scheduler.isShutdown()) { scheduler.shutdown(); return; } UIUtil.invokeLaterIfNeeded(() -> progressBar.setValue(incrementProgress())); }, 0, STEP_HEARTBEAT, TimeUnit.MILLISECONDS); } /** * 递增进度条 * * @return 进度值 */ public int incrementProgress() { if (progress != progressBar.getMaximum()) { progress += step; } return progress; } @Override public void onClose() { this.progress = progressBar.getMaximum(); } /** * 重置进度条 */ public void reset() { this.progress = 0; } /** * 进度是否已结束 * * @return 进度结束状态 */ public boolean isComplete() { return this.progress >= progressBar.getMaximum(); } }