如何在JDesktopPane内的InternalFrame上方显示错误消息
在JDesktopPane内显示错误消息的解决方案
你遇到的问题根源是JDialog是顶层窗口,默认会脱离JDesktopPane的层级,显示在所有窗口上方。要在JDesktopPane内部嵌入消息窗口,应该使用JInternalFrame——这是Swing专门为JDesktopPane设计的内部容器组件。
核心修改步骤
- 将自定义类从继承
JDialog改为继承JInternalFrame - 调整构造方法,适配JInternalFrame的初始化参数
- 修改显示逻辑:将内部窗口添加到JDesktopPane中,而非直接调用
setVisible(true) - 保留原有动画、UI组件和交互逻辑,仅替换容器类型
修改后的完整代码
自定义错误消息内部窗口类
package com.mutale.posapplication.dialogs; import com.mutale.posapplication.scroll.ScrollBarCustom; import com.mutale.posapplication.swing.icons.GoogleMaterialDesignIcons; import com.mutale.posapplication.swing.icons.IconFontSwing; import java.awt.Color; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.border.EmptyBorder; import org.jdesktop.animation.timing.Animator; import org.jdesktop.animation.timing.TimingTargetAdapter; import javax.swing.JInternalFrame; public class ErrorDisplay extends JInternalFrame { private String icon; private boolean ok; private final Animator animator; private boolean show = true; public boolean isOk() { return ok; } public void setOk(boolean ok) { this.ok = ok; } public ErrorDisplay(String icon1) { // 初始化JInternalFrame:关闭可交互,其余功能禁用(保持原弹窗样式) super("", false, false, false, false); initComponents(); icon = "1"; panel(error_ScrollPane); lbMessage.setLineWrap(true); lbMessage.setWrapStyleWord(true); setOpacity(0f); // 保留原图标设置逻辑 if(icon.equals(icon1)){ lbIcon.setIcon(IconFontSwing.buildIcon(GoogleMaterialDesignIcons.STORAGE, 60, new Color(254, 86, 96), new Color(113, 74, 67))); }else{ lbIcon.setIcon(IconFontSwing.buildIcon(GoogleMaterialDesignIcons.REPORT_PROBLEM, 40, new Color(254, 86, 96), new Color(113, 74, 67))); } getContentPane().setBackground(Color.WHITE); // 保留原动画逻辑 TimingTargetAdapter target = new TimingTargetAdapter() { @Override public void timingEvent(float fraction) { if (show) { setOpacity(fraction); } else { setOpacity(1f - fraction); } } @Override public void end() { if (!show) { setVisible(false); // 关闭后从JDesktopPane移除组件,避免内存泄漏 getDesktopPane().remove(ErrorDisplay.this); getDesktopPane().repaint(); } } }; animator = new Animator(200, target); animator.setResolution(0); animator.setAcceleration(0.5f); } public void showMessage(String message, javax.swing.JDesktopPane desktopPane) { lbMessage.setText(message); // 设置窗口在JDesktopPane中居中显示 setSize(getPreferredSize()); int x = (desktopPane.getWidth() - getWidth()) / 2; int y = (desktopPane.getHeight() - getHeight()) / 2; setLocation(x, y); // 添加到JDesktopPane并显示 desktopPane.add(this); animator.start(); setVisible(true); moveToFront(); // 确保窗口在内部层级最上层 } public final void panel(JScrollPane scroll) { scroll.getViewport().setBackground(Color.WHITE); scroll.setVerticalScrollBar(new ScrollBarCustom()); JPanel p = new JPanel(); p.setBackground(Color.WHITE); scroll.setCorner(JScrollPane.UPPER_RIGHT_CORNER, p); scroll.setBorder(new EmptyBorder(0, 0, 0, 0)); } @SuppressWarnings("unchecked") private void initComponents() { jPanel1 = new javax.swing.JPanel(); lbIcon = new javax.swing.JLabel(); cancele = new com.mutale.posapplication.swings.Button(); error_ScrollPane = new javax.swing.JScrollPane(); lbMessage = new javax.swing.JTextArea(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); setUndecorated(true); setResizable(false); jPanel1.setBackground(new java.awt.Color(255, 255, 255)); jPanel1.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(204, 0, 0), 2)); lbIcon.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); cancele.setBackground(new java.awt.Color(202, 5, 5)); cancele.setText("X"); cancele.setToolTipText("close"); cancele.setColorGradient(new java.awt.Color(202, 5, 5)); cancele.setEnabled(false); cancele.setFont(new java.awt.Font("Tahoma", 1, 12)); cancele.addMouseListener(new java.awt.event.MouseAdapter() { public void mousePressed(java.awt.event.MouseEvent evt) { canceleMousePressed(evt); } }); lbMessage.setEditable(false); lbMessage.setColumns(3); lbMessage.setFont(new java.awt.Font("Times New Roman", 0, 14)); lbMessage.setRows(4); lbMessage.setAutoscrolls(false); lbMessage.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0)); error_ScrollPane.setViewportView(lbMessage); javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(jPanel1Layout.createSequentialGroup() .addComponent(lbIcon, javax.swing.GroupLayout.PREFERRED_SIZE, 26, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(cancele, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addComponent(error_ScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 540, Short.MAX_VALUE) ); jPanel1Layout.setVerticalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addComponent(cancele, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(lbIcon, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addGap(1, 1, 1) .addComponent(error_ScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 331, Short.MAX_VALUE)) ); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ); pack(); } private void canceleMousePressed(java.awt.event.MouseEvent evt) { ok = true; closeMenu(); } private void closeMenu() { if (animator.isRunning()) { animator.stop(); } show = false; animator.start(); } // Variables declaration - do not modify private com.mutale.posapplication.swings.Button cancele; private javax.swing.JScrollPane error_ScrollPane; private javax.swing.JPanel jPanel1; private javax.swing.JLabel lbIcon; private javax.swing.JTextArea lbMessage; // End of variables declaration }
修改后的调用代码
private boolean showAdmin_T() { // 获取主窗口中的JDesktopPane javax.swing.JDesktopPane desktopPane = fram.getDesktopPane(); ErrorDisplay obj = new ErrorDisplay("1"); // 传入JDesktopPane并显示消息 obj.showMessage("你的错误消息内容", desktopPane); return obj.isOk(); }
关键说明
JInternalFrame是JDesktopPane的专属内部窗口,会受JDesktopPane的层级管理,不会跳出到外部窗口- 调用时必须传入JDesktopPane实例,才能将内部窗口添加到其中
- 保留了原有的动画效果和UI样式,仅替换容器类型
- 关闭窗口时主动从JDesktopPane移除组件,避免内存泄漏
内容的提问来源于stack exchange,提问作者kabwe
相关产品推荐
相关产品推荐

