在 JFrame 和 JDialog 之间传递容器导致面板丢失?
Passing containers between JFrame and JDialog causing missing panels?
至于测试原因,我尝试打开一个 JDialog window,其中包含面板及其主应用程序框架的内容。因为我已经有任何东西在那里我想看看我是否可以简单地将 JDialogs contentPane 设置为我传递的那个。因此,以简单的形式,它们组合在一起:
testsforSO.java :
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class testsforSO extends JFrame {
private static final long serialVersionUID = -3890178393751567629L;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
testsforSO frame = new testsforSO();
frame.setSize(300, 300);
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public testsforSO() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("I am the Frame");
getContentPane().setLayout(new BorderLayout(0, 0));
JPanel panel = new JPanel();
panel.setLayout(null);
JButton btnRestart = new JButton("Restart");
btnRestart.setBounds(10, 10, 50, 50);
btnRestart.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
testsforSO.main(null);
dispose();
}
});
panel.add(btnRestart);
getContentPane().add(panel);
repaint();
// -----------DELETE These comments-------------
// JDialog myDialg = new JDialog(this);
// myDialg.setContentPane(panel);
// myDialg.setVisible(true);
// myDialg.setSize(300,300);
// myDialg.setLocation(new Point(250, 250));
// myDialg.setTitle("I am Dialog from within the script");
myDialog.main(panel);
}
}
和myDialog.java:
import java.awt.Container;
import java.awt.EventQueue;
import javax.swing.JDialog;
public class myDialog extends JDialog {
private static final long serialVersionUID = 7079322237622743228L;
public static void main(Container myContainer) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
myDialog frame = new myDialog(myContainer);
frame.setVisible(true);
frame.setContentPane(myContainer);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public myDialog(Container myContainer) {
setContentPane(myContainer);
getContentPane().setLayout(null);
setBounds(200,200,200,200);
}
}
启动主框架时,我假设它会像对话框一样包含重新启动按钮。但有趣的是,它只是带有按钮的对话框。
然而,当点击它时,主框架正确重启,设置了第二个对话框,它再次包含按钮。不过这次主机也有按钮,只是没有任何功能。单击它绝对没有任何作用。
然后我进一步尝试并检查如果我将对话框直接添加到主应用程序代码中(请参阅注释行)并且再次启动应用程序时该行为是否会改变 class 显示按钮。即使点击这个按钮现在可以正确重新启动,但按钮不会出现在任何其他 window 上,除了孤独的声明对话框。
我在这里遗漏了什么?即使以这种方式,我如何重构我的代码才能正常工作?
了解 Swing 组件只能存在于一个容器中,虽然您可能会看到容器中组件的视觉残留,但实际组件仅存在于最后添加的容器中。
我自己,如果我希望 dialog 和 jframe 具有相同的内容窗格组件,我会创建一个工厂方法来创建 contentPane,然后使用它来创建两个独特但相同的 contentPanes。
此外,如果我不提及您对空布局的使用,那将是我的失职。虽然空布局和 setBounds()
对于 Swing 新手来说似乎是创建复杂 GUI 的最简单和最好的方法,但您创建的 Swing GUI 越多,您在使用它们时 运行 就会遇到更严重的困难。它们不会在 GUI 调整大小时调整您的组件的大小,它们是皇家 来增强或维护的,当放置在滚动窗格中时它们会完全失败,当在所有平台或不同的屏幕分辨率上查看时它们看起来很糟糕从原来的。
例如,当我运行你的代码时,这是我看到的对话框:
您将按钮的大小硬编码为太小,无法在我的平台上显示其文本。如果您使用了布局管理器,并在顶层 window 上调用了 pack()
,该按钮将正确显示。
至于测试原因,我尝试打开一个 JDialog window,其中包含面板及其主应用程序框架的内容。因为我已经有任何东西在那里我想看看我是否可以简单地将 JDialogs contentPane 设置为我传递的那个。因此,以简单的形式,它们组合在一起:
testsforSO.java :
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class testsforSO extends JFrame {
private static final long serialVersionUID = -3890178393751567629L;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
testsforSO frame = new testsforSO();
frame.setSize(300, 300);
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public testsforSO() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setTitle("I am the Frame");
getContentPane().setLayout(new BorderLayout(0, 0));
JPanel panel = new JPanel();
panel.setLayout(null);
JButton btnRestart = new JButton("Restart");
btnRestart.setBounds(10, 10, 50, 50);
btnRestart.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
testsforSO.main(null);
dispose();
}
});
panel.add(btnRestart);
getContentPane().add(panel);
repaint();
// -----------DELETE These comments-------------
// JDialog myDialg = new JDialog(this);
// myDialg.setContentPane(panel);
// myDialg.setVisible(true);
// myDialg.setSize(300,300);
// myDialg.setLocation(new Point(250, 250));
// myDialg.setTitle("I am Dialog from within the script");
myDialog.main(panel);
}
}
和myDialog.java:
import java.awt.Container;
import java.awt.EventQueue;
import javax.swing.JDialog;
public class myDialog extends JDialog {
private static final long serialVersionUID = 7079322237622743228L;
public static void main(Container myContainer) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
myDialog frame = new myDialog(myContainer);
frame.setVisible(true);
frame.setContentPane(myContainer);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public myDialog(Container myContainer) {
setContentPane(myContainer);
getContentPane().setLayout(null);
setBounds(200,200,200,200);
}
}
启动主框架时,我假设它会像对话框一样包含重新启动按钮。但有趣的是,它只是带有按钮的对话框。
然而,当点击它时,主框架正确重启,设置了第二个对话框,它再次包含按钮。不过这次主机也有按钮,只是没有任何功能。单击它绝对没有任何作用。
然后我进一步尝试并检查如果我将对话框直接添加到主应用程序代码中(请参阅注释行)并且再次启动应用程序时该行为是否会改变 class 显示按钮。即使点击这个按钮现在可以正确重新启动,但按钮不会出现在任何其他 window 上,除了孤独的声明对话框。
我在这里遗漏了什么?即使以这种方式,我如何重构我的代码才能正常工作?
了解 Swing 组件只能存在于一个容器中,虽然您可能会看到容器中组件的视觉残留,但实际组件仅存在于最后添加的容器中。
我自己,如果我希望 dialog 和 jframe 具有相同的内容窗格组件,我会创建一个工厂方法来创建 contentPane,然后使用它来创建两个独特但相同的 contentPanes。
此外,如果我不提及您对空布局的使用,那将是我的失职。虽然空布局和 setBounds()
对于 Swing 新手来说似乎是创建复杂 GUI 的最简单和最好的方法,但您创建的 Swing GUI 越多,您在使用它们时 运行 就会遇到更严重的困难。它们不会在 GUI 调整大小时调整您的组件的大小,它们是皇家 来增强或维护的,当放置在滚动窗格中时它们会完全失败,当在所有平台或不同的屏幕分辨率上查看时它们看起来很糟糕从原来的。
例如,当我运行你的代码时,这是我看到的对话框:
您将按钮的大小硬编码为太小,无法在我的平台上显示其文本。如果您使用了布局管理器,并在顶层 window 上调用了 pack()
,该按钮将正确显示。