消除BorderLayout中JPanel之间的间隙

3
我正在将两个JPanel(CENTER和PAGE_END)添加到另一个JPanel中,然后再将其放入JFrame中。这两个面板(panneauDateDebut和panneauDateFin)之间存在巨大的间隙,我希望消除这个间隙。我尝试过不同的配置(start/center、start/end、center/end),但没有成功。请问该怎么做?

为了让代码能够正常工作,在此提供一份可用的代码

import java.awt.BorderLayout;
import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.GridLayout;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class CreerModificationAbsence extends JDialog {

    private JPanel modificationAbsence1, modificationAbsence2,
            modificationAbsence3, panneauDateDebut, panneauDateFin;
    private JButton modifier, annuler;
    private JLabel raison, prenomNomEmpl, prenomNomChef;
    private JComboBox<String> raisonC, heureDebutC, heureFinC, minuteDebutC,
            minuteFinC;
    private JTextField prenomNomEmplT, prenomnomChefT;
    private final String[] raisonAbsence = { "Malade" };

    private JLabel dateDebut, dateFin;
    private JTextField dateDebutT, dateFinT;

    private final String[] heures = { "00" };
    private final String[] minutes = { "00", "15", "30", "45" };

    private BorderLayout gestionnaireComposant;
    private GridLayout gridGestionnaireComposant;
    private FlowLayout panneauMilieuLayout;
    final FlowLayout gestionnaireComposantBas;

    public CreerModificationAbsence() {
        super((Frame) null, "Modification - Absence d'employé", true);

        setPreferredSize(new Dimension(600, 250));
        setAlwaysOnTop(true);
        setResizable(false);
        setLocation(400, 200);
        setAlwaysOnTop(true);
        gestionnaireComposant = new BorderLayout();
        this.getContentPane().setLayout(gestionnaireComposant);

        // Modification Panneau Haut

        modificationAbsence1 = new JPanel();

        gridGestionnaireComposant = new GridLayout(3, 2, 2, 2);
        modificationAbsence1.setLayout(gridGestionnaireComposant);

        raison = new JLabel("Raison : ");
        raisonC = new JComboBox<>(raisonAbsence);
        raisonC.setEditable(true);
        prenomNomEmpl = new JLabel("Prénom et Nom de l'employé : ");
        prenomNomEmplT = new JTextField();
        prenomNomChef = new JLabel("Prénom et Nom du chef d'équipe : ");
        prenomnomChefT = new JTextField();

        modificationAbsence1.add(raison);
        modificationAbsence1.add(raisonC);
        modificationAbsence1.add(prenomNomEmpl);
        modificationAbsence1.add(prenomNomEmplT);
        modificationAbsence1.add(prenomNomChef);
        modificationAbsence1.add(prenomnomChefT);

        // Modification Panneau Milieu

        modificationAbsence2 = new JPanel();
        panneauDateDebut = new JPanel();
        panneauDateFin = new JPanel();

        panneauMilieuLayout = new FlowLayout();

        panneauDateDebut.setLayout(panneauMilieuLayout);
        panneauDateDebut.setPreferredSize(new Dimension(600, 0));
                   panneauDateDebut.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);

        panneauDateFin.setLayout(panneauMilieuLayout);
        panneauDateFin.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
        panneauDateFin.setPreferredSize(new Dimension(600, 113));

        modificationAbsence2.setLayout(new BorderLayout(0,0));

        dateDebutT = new JTextField(12);
        heureDebutC = new JComboBox<>(heures);
        minuteDebutC = new JComboBox<>(minutes);
        dateFinT = new JTextField(12);
        heureFinC = new JComboBox<>(heures);
        minuteFinC = new JComboBox<>(minutes);

        dateDebut = new JLabel("Date de début :");
        dateFin = new JLabel("Date de fin :");

        dateDebutT.setPreferredSize(new Dimension(125, 20));
        dateFinT.setPreferredSize(new Dimension(125, 20));
        dateDebut.setPreferredSize(new Dimension(125, 20));
        dateFin.setPreferredSize(new Dimension(125, 20));
        heureDebutC.setPreferredSize(new Dimension(130, 20));
        minuteDebutC.setPreferredSize(new Dimension(130, 20));
        heureFinC.setPreferredSize(new Dimension(130, 20));
        minuteFinC.setPreferredSize(new Dimension(130, 20));

        panneauDateDebut.add(dateDebut);
        panneauDateDebut.add(dateDebutT);
        panneauDateDebut.add(heureDebutC);
        panneauDateDebut.add(minuteDebutC);
        panneauDateFin.add(dateFin);
        panneauDateFin.add(dateFinT);
        panneauDateFin.add(heureFinC);
        panneauDateFin.add(minuteFinC);
        modificationAbsence2.add(panneauDateDebut, BorderLayout.CENTER);
        modificationAbsence2.add(panneauDateFin, BorderLayout.PAGE_END);

        // Modification Panneau Bas

        modificationAbsence3 = new JPanel();
        gestionnaireComposantBas = new FlowLayout(FlowLayout.RIGHT);
        modificationAbsence3.setLayout(gestionnaireComposantBas);

        modifier = new JButton("Modifier");
        annuler = new JButton("Annuler");

        modificationAbsence3.add(modifier);
        modificationAbsence3.add(annuler);

        this.add(modificationAbsence1, BorderLayout.NORTH);
        this.add(modificationAbsence2, BorderLayout.CENTER);
        this.add(modificationAbsence3, BorderLayout.SOUTH);
        /*this.*/setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        this.pack();
            /*this.*/setVisible(true);
    }

 public static void main(String s[]) {
    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            CreerModificationAbsence textf = new CreerModificationAbsence();
        }
    });
}


}

这段代码中两个面板之间有一个巨大的间隙,没有讲述如何将父级JPanel放置到JFrame中。为了更好地帮助解决问题,请发布一个SSCCE,演示您遇到的问题,该演示应该简短、可运行和可编译。 - mKorbel
我相信你不能看到所有的JComponents :-),你所描述的不是真实情况,也不是一个SSCCE,我会添加剩下的。 - mKorbel
请问你能否在画图软件中创建一张图片,它应该是什么样子的? - mKorbel
抱歉,我忘了提到我通过使用panneauDateFin.setPreferredSize(new Dimension(600, 113))进行了一些欺骗。将其设置为113使其接近上面的其他面板。 - Mobidoy
如果你将以下代码注释掉:panneauDateDebut.setPreferredSize(new Dimension(600, 0)); panneauDateFin.setPreferredSize(new Dimension(600, 113));你会看到它不应该是这个样子的 :-) - Mobidoy
2个回答

3

首先,不要使用setPreferredSize()方法!这是导致你所有问题的根源。永远停止使用它(不开心别生气 ~开个玩笑)并且你将解决所有问题。

尝试使用以下方法代替:

import java.awt.BorderLayout;
import java.awt.ComponentOrientation;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.GridLayout;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class CreerModificationAbsence extends JDialog {

    private JPanel modificationAbsence1, modificationAbsence2, modificationAbsence3, panneauDateDebut, panneauDateFin;
    private JButton modifier, annuler;
    private JLabel raison, prenomNomEmpl, prenomNomChef;
    private JComboBox<String> raisonC, heureDebutC, heureFinC, minuteDebutC, minuteFinC;
    private JTextField prenomNomEmplT, prenomnomChefT;
    private final String[] raisonAbsence = { "Malade" };

    private JLabel dateDebut, dateFin;
    private JTextField dateDebutT, dateFinT;

    private final String[] heures = { "00" };
    private final String[] minutes = { "00", "15", "30", "45" };

    private BorderLayout gestionnaireComposant;
    private GridLayout gridGestionnaireComposant;
    private FlowLayout panneauMilieuLayout;
    final FlowLayout gestionnaireComposantBas;

    public CreerModificationAbsence() {
        super((Frame) null, "Modification - Absence d'employé", true);

        // setPreferredSize(new Dimension(600, 250));
        setAlwaysOnTop(true);
        setResizable(false);
        setAlwaysOnTop(true);
        gestionnaireComposant = new BorderLayout();
        this.getContentPane().setLayout(gestionnaireComposant);

        // Modification Panneau Haut

        modificationAbsence1 = new JPanel();

        gridGestionnaireComposant = new GridLayout(3, 2, 2, 2);
        modificationAbsence1.setLayout(gridGestionnaireComposant);

        raison = new JLabel("Raison : ");
        raisonC = new JComboBox(raisonAbsence);
        raisonC.setEditable(true);
        prenomNomEmpl = new JLabel("Prénom et Nom de l'employé : ");
        prenomNomEmplT = new JTextField();
        prenomNomChef = new JLabel("Prénom et Nom du chef d'équipe : ");
        prenomnomChefT = new JTextField();

        modificationAbsence1.add(raison);
        modificationAbsence1.add(raisonC);
        modificationAbsence1.add(prenomNomEmpl);
        modificationAbsence1.add(prenomNomEmplT);
        modificationAbsence1.add(prenomNomChef);
        modificationAbsence1.add(prenomnomChefT);

        // Modification Panneau Milieu

        modificationAbsence2 = new JPanel();
        panneauDateDebut = new JPanel();
        panneauDateFin = new JPanel();

        panneauMilieuLayout = new FlowLayout();

        panneauDateDebut.setLayout(panneauMilieuLayout);
        panneauDateDebut.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);

        panneauDateFin.setLayout(panneauMilieuLayout);
        panneauDateFin.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);

        dateDebutT = new JTextField(12);
        heureDebutC = new JComboBox(heures);
        minuteDebutC = new JComboBox(minutes);
        dateFinT = new JTextField(12);
        heureFinC = new JComboBox(heures);
        minuteFinC = new JComboBox(minutes);

        dateDebut = new JLabel("Date de début :");
        dateFin = new JLabel("Date de fin :");

        panneauDateDebut.add(dateDebut);
        panneauDateDebut.add(dateDebutT);
        panneauDateDebut.add(heureDebutC);
        panneauDateDebut.add(minuteDebutC);
        panneauDateFin.add(dateFin);
        panneauDateFin.add(dateFinT);
        panneauDateFin.add(heureFinC);
        panneauDateFin.add(minuteFinC);
        modificationAbsence2.add(panneauDateDebut, BorderLayout.CENTER);
        modificationAbsence2.add(panneauDateFin, BorderLayout.PAGE_END);

        // Modification Panneau Bas

        modificationAbsence3 = new JPanel();
        gestionnaireComposantBas = new FlowLayout(FlowLayout.RIGHT);
        modificationAbsence3.setLayout(gestionnaireComposantBas);

        modifier = new JButton("Modifier");
        annuler = new JButton("Annuler");

        modificationAbsence3.add(modifier);
        modificationAbsence3.add(annuler);

        this.add(modificationAbsence1, BorderLayout.NORTH);
        this.add(modificationAbsence2, BorderLayout.CENTER);
        this.add(modificationAbsence3, BorderLayout.SOUTH);
        /*this.*/setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        this.pack();
        setLocationRelativeTo(null);
        /*this.*/setVisible(true);
    }

    public static void main(String s[]) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                CreerModificationAbsence textf = new CreerModificationAbsence();
            }
        });
    }

}

+1 先你一步了!不过我还是发布了,因为我快完成了。 - Nick Rippe
哇,这很有帮助,只有一个问题,如果我删除dateDebutT.setPreferredSize(new Dimension(125, 20)); dateFinT.setPreferredSize(new Dimension(125, 20)); dateDebut.setPreferredSize(new Dimension(125, 20)); dateFin.setPreferredSize(new Dimension(125, 20)); heureDebutC.setPreferredSize(new Dimension(130, 20)); minuteDebutC.setPreferredSize(new Dimension(130, 20)); heureFinC.setPreferredSize(new Dimension(130, 20)); minuteFinC.setPreferredSize(new Dimension(130, 20));那么我的按钮大小就不对了,除了setPreferredSize之外,我该如何让它们采用这些尺寸? - Mobidoy
@Mobidoy 没问题。你的意思是,它们没有合适的尺寸吗?你期望它们是什么尺寸?如果你想让它们都是相同的尺寸,我建议将它们包装在一个使用 GridLayout 作为布局管理器的 JPanel 中。无论如何,设置首选大小总是会导致麻烦的结果和不良影响。此外,它也不易于维护(想象一下,明天你决定将所有组件的字体设置为 24px,你必须修改所有首选大小),并且与其他 L&F 不兼容。 - Guillaume Polet

3
你遇到的问题是因为你在上使用了setPreferredSize方法。这样做会导致对话框必须保持给定的大小。因为它现在必须保持这个大小,所以就需要一些东西来适应。这就是布局管理器发挥作用的地方。在边界布局(BorderLayout)中,无论什么东西在中心位置都将被拉伸。
如果你设置两个面板的背景颜色,就可以看到正在发生的事情了:
    panneauDateDebut = new JPanel();
    panneauDateDebut.setOpaque(true);
    panneauDateDebut.setBackground(Color.blue);
    panneauDateFin = new JPanel();
    panneauDateFin.setOpaque(true);
    panneauDateFin.setBackground(Color.green);

解决方案(Guillaume在我写作时指出)是停止使用setPreferredSize。因此,如果您的构造函数看起来像下面这样,则应该解决问题:
public PageCentering() {
        super((Frame) null, "Modification - Absence d'employé", true);

        //setPreferredSize(new Dimension(600, 250));

        ...

}

谢谢Nick,它确实起作用了...只是现在我的组合框等在那个面板中太小了! - Mobidoy
@Mobidoy 嘿 - 这就是为什么我最喜欢BoxLayout。对于我的风格,它让我在额外空间的放置上拥有最多的控制权(尽管它也有自己的怪癖)。如果你想要一个从上到下布局的东西,只需使用Box container = Box.createVerticalBox()而不是JPanel container = new JPanel。然后在你想要留出空白的地方添加container.add(Box.createVerticalGlue())即可。 - Nick Rippe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接