参考下面的 links,做了一个 semi-modal JInternalFrame:
Creating Modal Internal Frames -- Approach 1 and Approach 2
Java GUI - Make JInternalFrame behave like modal dialog
Java Technology Forums - Modal Internal Frames and JCombos
import java.beans.*;
import javax.swing.*;
public class JXFrame extends JFrame implements VetoableChangeListener {
public void vetoableChange(PropertyChangeEvent evt)
throws PropertyVetoException {
if (evt.getPropertyName().equals(JXInternalFrame.IS_SELECTED_PROPERTY)) {
if(evt.getSource() instanceof JXInternalFrame) {
JXInternalFrame frame = (JXInternalFrame)evt.getSource();
frame.selectChild();
}
throw new PropertyVetoException("Selected", null);
}
}
}
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;
public class JXInternalFrame extends JInternalFrame {
private boolean modal = false;
private JXInternalFrame parent = null;
private JXInternalFrame child = null;
private static JXFrame desktopFrame = null;
private Component originalGlassPane;
private GalssPaneForModal modalGlassPane;
private Integer defaultCloseOperation = null;
public JXInternalFrame() {
super();
}
public JXInternalFrame(String title) {
super(title, true, true, true, true);
}
public JXInternalFrame(JXInternalFrame parent, boolean modal, String title) {
super(title, true, true, true, true);
this.parent = parent;
if (modal) {
startModal();
}
}
public JXInternalFrame(String title, boolean resizable) {
super(title, resizable);
}
public JXInternalFrame(String title, boolean resizable, boolean closable) {
super(title, resizable, closable);
}
public JXInternalFrame(String title, boolean resizable, boolean closable,
boolean maximizable) {
super(title, resizable, closable, maximizable);
}
public JXInternalFrame(String title, boolean resizable, boolean closable,
boolean maximizable, boolean iconifiable) {
super(title, resizable, closable, maximizable, iconifiable);
}
public boolean isModal() {
return modal;
}
public void startModal() {
if (!modal && parent != null && desktopFrame != null) {
parent.setChild(this);
originalGlassPane = parent.getGlassPane();
modalGlassPane = new GalssPaneForModal();
modalGlassPane.containerFrame = parent;
parent.setGlassPane(modalGlassPane);
parent.addVetoableChangeListener(desktopFrame);
defaultCloseOperation = parent.getDefaultCloseOperation();
parent.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
modal = true;
}
}
public void stopModal() {
if (modal && parent != null && desktopFrame != null) {
parent.setGlassPane(originalGlassPane);
parent.removeVetoableChangeListener(desktopFrame);
if (defaultCloseOperation != null) {
parent.setDefaultCloseOperation(defaultCloseOperation);
}
try {
parent.setSelected(true);
if(parent.isIcon)
parent.setIcon(false);
} catch (PropertyVetoException e) {
// TODO: handle exception
}
modal = false;
}
}
public void setVisible(boolean visible) {
super.setVisible(visible);
if (!visible) {
stopModal();
}
}
public static void setDesktopFrame(JXFrame desktopFrame) {
JXInternalFrame.desktopFrame = desktopFrame;
}
public JXInternalFrame getChild() {
return child;
}
public void setChild(JXInternalFrame child) {
this.child = child;
}
public void selectChild() {
JXInternalFrame child = this;
while(child.getChild() != null)
child = child.getChild();
try {
child.setSelected(true);
} catch (PropertyVetoException exception) {
// TODO: handle exception
}
}
}
class GalssPaneForModal extends JComponent {
JXInternalFrame containerFrame = null;
public void setVisible(boolean visible) {
super.setVisible(true);
}
public GalssPaneForModal() {
this.setOpaque(false);
MouseInputAdapter listener = new MouseInputAdapter() {
@Override
public void mousePressed(MouseEvent e) {
containerFrame.selectChild();
}
};
addMouseListener(listener);
addMouseMotionListener(listener);
}
}