Java 如何等待JDialog完全创建

Java 如何等待JDialog完全创建,java,swing,jdialog,Java,Swing,Jdialog,我需要计算一下窗户的装饰。所以我重写了JDialog的构造函数。但是当我调用get\u decoration\u size()时,它有时返回错误的值。我的想法是:窗口创建晚于get\u decoration\u size()执行(奇怪,因为两者都在同一个线程和同一个构造函数中)。所以我决定睡一会儿,它成功了,现在装饰总是有效的 我的问题是:是否有一种方法可以“加入”到创建过程中(等待窗口显示为setVisible(true))?如果是这样的话,它一定是用来取代不安全睡眠(1000)的东西 为了创

我需要计算一下窗户的装饰。所以我重写了JDialog的构造函数。但是当我调用
get\u decoration\u size()
时,它有时返回错误的值。我的想法是:窗口创建晚于
get\u decoration\u size()
执行(奇怪,因为两者都在同一个线程和同一个构造函数中)。所以我决定睡一会儿,它成功了,现在装饰总是有效的

我的问题是:是否有一种方法可以“加入”到创建过程中(等待窗口显示为
setVisible(true)
)?如果是这样的话,它一定是用来取代不安全睡眠(1000)的东西


为了创建一个可运行的示例,我必须进行大量假设

下面是getDecorationSize方法的结果。直到我关闭JDialog,这行才打印出来

java.awt.Dimension[width=16,height=39]
这是我使用的代码

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class JDialogTest implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new JDialogTest());
    }

    private JFrame frame;

    @Override
    public void run() {
        frame = new JFrame("JDialog Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(createMainPanel());

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private JPanel createMainPanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(
                150, 100, 150, 100));
        panel.setPreferredSize(new Dimension(400, 400));

        JButton button = new JButton("Open JDialog");
        button.addActionListener(new ButtonListener());
        panel.add(button);

        return panel;
    }

    public class ButtonListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            new CalculateDecor(frame, "Spash Screen");
        }

    }

    public class CalculateDecor extends JDialog {

        private static final long serialVersionUID = 1L;

        public CalculateDecor(JFrame frame, String title) {
            super(frame, true);
            setDefaultCloseOperation(DISPOSE_ON_CLOSE);
            setTitle(title);

            JPanel panel = new JPanel(new BorderLayout());
            panel.setPreferredSize(new Dimension(200, 200));

            JLabel label = new JLabel("Loading...");
            label.setHorizontalAlignment(JLabel.CENTER);
            panel.add(label);

            add(panel);
            pack();
            setLocationRelativeTo(frame);
            setVisible(true);

            System.out.println(getDecorationSize());
        }

        private Dimension getDecorationSize() {
            Rectangle window = getBounds();
            Rectangle content = getContentPane().getBounds();
            int width = window.width - content.width;
            int height = window.height - content.height;
            return new Dimension(width, height);
        }

    }

}

“我需要计算一下窗户的装饰。”。。。为什么?请参阅一般提示:为了更快地获得更好的帮助,请添加or。我以前没有注意到
setLayout(null)。。Java GUI必须在不同的操作系统、屏幕大小、屏幕分辨率等上工作,在不同的地区使用不同的PLAF。因此,它们不利于像素完美布局。而是使用布局管理器,或与布局填充和边框一起使用。
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class JDialogTest implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new JDialogTest());
    }

    private JFrame frame;

    @Override
    public void run() {
        frame = new JFrame("JDialog Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(createMainPanel());

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private JPanel createMainPanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(
                150, 100, 150, 100));
        panel.setPreferredSize(new Dimension(400, 400));

        JButton button = new JButton("Open JDialog");
        button.addActionListener(new ButtonListener());
        panel.add(button);

        return panel;
    }

    public class ButtonListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            new CalculateDecor(frame, "Spash Screen");
        }

    }

    public class CalculateDecor extends JDialog {

        private static final long serialVersionUID = 1L;

        public CalculateDecor(JFrame frame, String title) {
            super(frame, true);
            setDefaultCloseOperation(DISPOSE_ON_CLOSE);
            setTitle(title);

            JPanel panel = new JPanel(new BorderLayout());
            panel.setPreferredSize(new Dimension(200, 200));

            JLabel label = new JLabel("Loading...");
            label.setHorizontalAlignment(JLabel.CENTER);
            panel.add(label);

            add(panel);
            pack();
            setLocationRelativeTo(frame);
            setVisible(true);

            System.out.println(getDecorationSize());
        }

        private Dimension getDecorationSize() {
            Rectangle window = getBounds();
            Rectangle content = getContentPane().getBounds();
            int width = window.width - content.width;
            int height = window.height - content.height;
            return new Dimension(width, height);
        }

    }

}