效果如图
模态框是web开发中常用的一种组件,可以用作页面的内容的拓展\交互\提示等等, swing常见的组件不包含模态框, 窗口内组件jdialog或者jwindow的弹窗更像iframe那种二级窗口.
思路
- JLayeredPane 是一种层级面板,和h5中通过堆加zindex实现模态框层级是一样的.
- 所以默认内容作为第一层, 遮罩作为第二层(某些场景可以去除遮罩,或者设置透明度为0),模态框作为第三层
- 模态框弹出时禁用第一层的所有按钮, 当然也可以在事件中控制 点击第一层关闭第三层的模态框.(点击蒙层可关闭效果)
demo测试代码
dependencies:
- hutool (常用工具)
- flatlaf (美化)
- miglayout (布局)
- swingx-all (拓展组件)
com.mynote.core.**
- ColorBuilder 只是我常用的一些颜色汇总
- FrameUtil 只是为了快速测试JFrame使用
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.formdev.flatlaf.FlatLightLaf;
import com.mynote.core.ui.ColorBuilder;
import com.mynote.core.util.FrameUtil;
import net.miginfocom.swing.MigLayout;
import org.jdesktop.swingx.JXPanel;
import javax.swing.*;
import java.awt.*;
/**
* 模态框效果
*/
public class ModalPanelTest extends AbstractDefaultPanel {
private JButton showModal;
private JTextArea textArea;
private JLayeredPane layeredPane;
private JPanel content;
private JXPanel modalMask;
private JButton closeModal;
private JXPanel modalContent;
/**
* 初始化成员对象
*/
@Override
protected void init() {
layeredPane = new JLayeredPane();
createTextArea();
createModalButton();
createModalMask();
createModalContent();
content = new JPanel();
content.setLayout(new MigLayout("wrap 1"));
content.add(showModal, "align right");
content.add(new JScrollPane(textArea), "w 100%,h 100%");
}
/**
* 创建按钮
*/
void createModalButton() {
showModal = new JButton("showModal");
showModal.setBackground(ColorBuilder.BG_RED_COLOR1);
showModal.setForeground(ColorBuilder.LABEL_WHITE_COLOR1);
closeModal = new JButton("closeModal");
}
/**
* 创建文本域
*/
void createTextArea() {
textArea = new JTextArea(RandomUtil.randomString(3000));
textArea.setLineWrap(true);
}
/**
* 创建遮罩层
*/
void createModalMask() {
modalMask = new JXPanel();
modalMask.setLayout(new MigLayout("w 100%,h 100%"));
modalMask.setAlpha(0.5F);
modalMask.setOpaque(false);
modalMask.setBackground(ColorBuilder.LABEL_GRAY_COLOR1);
modalMask.setVisible(false);
}
/**
* 创建modal面板
*/
void createModalContent() {
modalContent = new JXPanel();
modalContent.setLayout(new MigLayout("wrap 1,center"));
modalContent.add(new JLabel(DateUtil.now()),"gaptop 50");
modalContent.add(new JTextField(), "w 200");
modalContent.setBackground(ColorBuilder.LABEL_WHITE_COLOR1);
modalContent.add(closeModal, "pos 1al 1al");
modalContent.setVisible(false);
}
/**
* render视图
*/
@Override
protected void render() {
view.add(layeredPane, "w 100%,h 100%");
// content 默认显示
layeredPane.setLayout(new MigLayout("wrap 1,w 100%,h 100%"));
layeredPane.setLayer(content, JLayeredPane.DEFAULT_LAYER);
layeredPane.add(content, "w 100%,h 100%");
// modalmask 绝对位置显示遮罩
layeredPane.setLayer(modalMask, JLayeredPane.PALETTE_LAYER);
layeredPane.add(modalMask, "pos 0.5al 0.5al,w 100%,h 100%");
// modalcontent 绝对位置显示模态框
layeredPane.setLayer(modalContent, JLayeredPane.MODAL_LAYER);
layeredPane.add(modalContent, "pos 0.5al 0.5al,w 70%,h 70%");
super.add(view, "w 100%,h 100%");
}
/**
* 绑定事件
*/
@Override
protected void bindEvents() {
showModal.addActionListener((e) -> {
modalMask.setVisible(true);
modalContent.setVisible(true);
setContentEnables(false);
});
closeModal.addActionListener((e) -> {
modalMask.setVisible(false);
modalContent.setVisible(false);
setContentEnables(true);
});
}
/**
* 是否禁用content面板
*
* @param enable
*/
void setContentEnables(boolean enable) {
Component[] components = content.getComponents();
for (Component comp : components) {
comp.setEnabled(enable);
System.out.println("当前节点:" + comp);
// jscrollpanel 需要找到viewport 特殊处理
if (comp instanceof JScrollPane) {
JViewport scrollView = (JViewport) ((JScrollPane) comp).getComponent(0);
Component[] scrollViewComps = scrollView.getComponents();
for (Component scrollViewComp : scrollViewComps) {
System.out.println("scroll节点:" + scrollViewComp);
scrollViewComp.setEnabled(enable);
}
}
}
}
public static void main(String[] args) {
FlatLightLaf.install();
FrameUtil.launchTest(new ModalPanelTest());
}
}