I Have the following code:
import java.awt.AWTEvent;
import java.awt.ActiveEvent;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.MenuComponent;
import java.awt.event.MouseEvent;
import javax.swing.JInternalFrame;
import javax.swing.SwingUtilities;
public class modalInternalFrame extends JInternalFrame {
// indica si aquest es modal o no.
boolean modal = false;
@Override
public void show() {
super.show();
if (this.modal) {
startModal();
}
}
@Override
public void setVisible(boolean value) {
super.setVisible(value);
if (modal) {
if (value) {
startModal();
} else {
stopModal();
}
}
}
private synchronized void startModal() {
try {
if (SwingUtilities.isEventDispatchThread()) {
EventQueue theQueue =
getToolkit().getSystemEventQueue();
while (isVisible()) {
AWTEvent event = theQueue.getNextEvent();
Object source = event.getSource();
boolean dispatch = true;
if (event instanceof MouseEvent) {
MouseEvent e = (MouseEvent) event;
MouseEvent m =
SwingUtilities.convertMouseEvent((Component) e.getSource(), e, this);
if (!this.contains(m.getPoint()) && e.getID() != MouseEvent.MOUSE_DRAGGED) {
dispatch = false;
}
}
if (dispatch) {
if (event instanceof ActiveEvent) {
((ActiveEvent) event).dispatch();
} else if (source instanceof Component) {
((Component) source).dispatchEvent(
event);
} else if (source instanceof MenuComponent) {
((MenuComponent) source).dispatchEvent(
event);
} else {
System.err.println(
"Unable to dispatch: " + event);
}
}
}
} else {
while (isVisible()) {
wait();
}
}
} catch (InterruptedException ignored) {
}
}
private synchronized void stopModal() {
notifyAll();
}
public void setModal(boolean modal) {
this.modal = modal;
}
public boolean isModal() {
return this.modal;
}
}
Then I used the NetBeans GUI to draw my JInternalFrame, but just changed the code in the class declaration to extend modalInternalFrame instead of JInternalFrame:
public class myDialog extends modalInternalFrame {
....
and then used this to actually display it from my top-level "desktop" JFrame (containing jDesktopPane1):
myDialog d = new myDialog();
d.setModal(true);
d.setBounds(160, 180, 550, 450);
jDesktopPane1.add(d);
d.setVisible(true);
My Problem is: If the internal frame has JComboBox or PopupMenu, when part of PopupMenu is out of the internal frame's boundry that part don't handle mouse event (you cann't scroll that part).
Any Ideas?
How about using the
JOptionPane.showInternalMessageDialog(...)
:There are three types of popups:
The only one that works in a modal state is the heavy weight popup. The "offical" way to change the popup's weight is through the
setLightWeightPopupEnabled(boolean aFlag)
method. If you set it false the popup will be medium weight when it's inside the application frame and heavy weight when exceeds the frame bounds.To force heavy weight, you have to use a client property called
javax.swing.ClientPropertyKey.PopupFactory_FORCE_HEAVYWEIGHT_POPUP
. With this property you can force popups (or every popup in a container) to be heavy weight. But the only way to access it is through reflection because it's private.Here is an example code:
If you put this inside your
modalInternalFrame
's contructor, then every popup placed on it will be heavy weight.