我有一个父窗口,它将启动另一个窗口。当子窗口启动时,我希望它显示为模态对话框。
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class ModalDialogTest {
public void createUI(){
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
JPanel mainPanel = new JPanel();
mainPanel.setBorder(BorderFactory.createEmptyBorder(200, 200, 200, 200));
JButton openButton = new JButton("Open a frame");
openButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
AnotherWindow anotherWindow = new AnotherWindow();
anotherWindow.createUI();
}
});
mainPanel.add(openButton,BorderLayout.CENTER);
frame.add(mainPanel,BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
ModalDialogTest modelDialogTest = new ModalDialogTest();
modelDialogTest.createUI();
}
class AnotherWindow{
public void createUI(){
JFrame frame = new JFrame("Dialog");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
JPanel mainPanel = new JPanel();
mainPanel.setBorder(BorderFactory.createEmptyBorder(100, 100, 100, 100));
JLabel label = new JLabel("I want to be a modal dialog");
mainPanel.add(label,BorderLayout.CENTER);
frame.add(mainPanel,BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
}
上面的演示描述了我的应用程序的过程,架构也是一样的。那么解决方案是什么?
答案 0 :(得分:6)
您无法设置JFrame
的模态;第二个窗口必须是JDialog
。因此,请将第二个JFrame
更改为JDialog
并在其上使用setModalityType()
方法。
答案 1 :(得分:5)
JFrame
无法成为模式,请改用JDialog
不要创建一堆JFrame
,而是使用JDialog
只创建一个JDialog
作为本地变量,在调用JDialog.getContentPane.removeAll()
之前,JDialog.setVisible(false)
重新使用此容器进行其他操作
注意Top-Level Containers
永远不会是GC,所有新实例都会增加使用的JVM内存,more details about here
答案 2 :(得分:1)
可以制作一个Frame模态,但你应该将JDialog作为标准选择。 这是一个我发现制作Frame模式的例子(代码适用于Java 1.4,但也适用于实际的java版本。)
static class EventPump implements InvocationHandler {
Frame frame;
public EventPump(Frame frame) {
this.frame = frame;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return frame.isShowing() ? Boolean.TRUE : Boolean.FALSE;
}
// when the reflection calls in this method has to be
// replaced once Sun provides a public API to pump events.
public void start() throws Exception {
final Class clazz = Class.forName("java.awt.Conditional");
final Object conditional = Proxy.newProxyInstance(clazz.getClassLoader(), new Class[] {clazz}, this);
final Method pumpMethod = Class.forName("java.awt.EventDispatchThread").getDeclaredMethod("pumpEvents", new Class[] {clazz});
pumpMethod.setAccessible(true);
pumpMethod.invoke(Thread.currentThread(), new Object[] {conditional});
}
}
// show the given frame as modal to the specified owner.
// NOTE: this method returns only after the modal frame is closed.
public static void showAsModal(final Frame frame, final Frame owner) {
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowOpened(WindowEvent e) {
owner.setEnabled(false);
}
@Override
public void windowClosed(WindowEvent e) {
owner.setEnabled(true);
frame.removeWindowListener(this);
}
});
owner.addWindowListener(new WindowAdapter() {
@Override
public void windowActivated(WindowEvent e) {
if (frame.isShowing()) {
frame.setExtendedState(JFrame.NORMAL);
frame.toFront();
} else {
owner.removeWindowListener(this);
}
}
});
frame.setVisible(true);
try {
new EventPump(frame).start();
} catch (final Throwable throwable) {
throw new RuntimeException(throwable); // NOPMD
}
}