Java GridBagLayout JPanels会自动调整大小问题吗?

时间:2015-03-15 21:25:40

标签: java swing jpanel jlabel gridbaglayout

我需要帮助调整红色JPanel的大小。基本上问题是我为RED和BLUE JPanel设置相同大小的网格包约束并且它工作完美,直到我添加JLabel,然后它只是愚蠢地开始使RED JPanel更大,但它应该与BLUE JPanel,应保持0.05大小。如果你能帮助我,我将非常感激,非常感谢你提前:))

http://s30.postimg.org/ag6fy7fg1/Screenshot_32.png

package weatherapp;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;

public class WeatherApp {

    JFrame mainFrame = new JFrame("Weather App");
    Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
    GridBagConstraints gbc = new GridBagConstraints();
    JPanel topMenuBar = new JPanel();
    JPanel weatherInfoMaster = new JPanel();
    JPanel weatherGraphMaster = new JPanel();
    JPanel bottomMenuBar = new JPanel();
    JLabel currentDateLabel = new JLabel(new SimpleDateFormat("dd MMMM yyyy").format(new Date()));

    WeatherApp() {
        constructAppFrame();
        constructTopMenuBar();
    }

    public void constructAppFrame() {
        mainFrame.setSize(540, 960);
        mainFrame.setPreferredSize(new Dimension(540, 960));
        //Terminate the program when the user closes the app.
        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        mainFrame.setResizable(false);
        mainFrame.setLocation(screenDimension.width / 2 - mainFrame.getSize().width / 2, screenDimension.height / 2 - mainFrame.getSize().height / 2);
        mainFrame.setLocationRelativeTo(null);
        mainFrame.setLayout(new GridBagLayout());

        gbc.fill = GridBagConstraints.BOTH;
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weightx = 1;
        gbc.weighty = 0.05;
        mainFrame.add(topMenuBar, gbc);
        gbc.gridy = 1;
        gbc.weighty = 0.6;
        mainFrame.add(weatherInfoMaster, gbc);
        gbc.gridy = 2;
        gbc.weighty = 0.5;
        mainFrame.add(weatherGraphMaster, gbc);
        gbc.gridy = 3;
        gbc.weighty = 0.05;
        mainFrame.add(bottomMenuBar, gbc);

        mainFrame.pack();
        mainFrame.setVisible(true);
    }

    public void constructTopMenuBar() {
        topMenuBar.setBackground(Color.RED);
        //topMenuBar.setBorder(new EmptyBorder(-20, 20, -20, 20));
        topMenuBar.setLayout(new BoxLayout(topMenuBar, BoxLayout.X_AXIS));
        currentDateLabel.setForeground(Color.WHITE);
        currentDateLabel.setFont(new Font("Comic Sans MS", Font.PLAIN, 20));
        currentDateLabel.setBackground(Color.BLUE);
        currentDateLabel.setOpaque(true);

        topMenuBar.add(currentDateLabel);

        weatherInfoMaster.setBackground(Color.CYAN);
        weatherGraphMaster.setBackground(Color.GREEN);
        bottomMenuBar.setBackground(Color.BLUE);
    }

    public static void main(String[] args) {
        //Create the frame on the event dispacthing thread.
        SwingUtilities.invokeLater(() -> {
            new WeatherApp();
        });
    }
}

1 个答案:

答案 0 :(得分:3)

//mainFrame.setLocation(screenDimension.width / 2 - mainFrame.getSize().width / 2, screenDimension.height / 2 - mainFrame.getSize().height / 2);
mainFrame.setLocationRelativeTo(null);

不需要第一个语句,因为setLocationRelativeTo(...)将重置位置。

constructAppFrame();
constructTopMenuBar();

在框架可见之后,不要向框架添加组件。两个陈述的顺序应该颠倒过来。

  

它只是愚蠢地开始使RED JPanel尺寸更大,但它应该与BLUE JPanel的尺寸相同,应保持0.05的大小。

这不是愚蠢的。它是布局管理器定义良好的行为。每个布局管理器都有自己的规则可供遵循。 GridBagLayout适用于"首选大小"组件。当没有组件添加到面板时,首选大小为(10,10),因为默认情况下JPanel使用FlowLayout,组件之前/之后的默认间隙为5像素。

因此,当有额外空间可用时,GridBagLayout会根据首选大小分配空间,从而导致红色占用更多空间。

快速破解(遵循上述其他建议),您可以:

bottomMenuBar.setPreferredSize( topMenuBar.getPreferredSize() );
mainFrame.add(bottomMenuBar, gbc);

现在尺寸将相同,因为首选尺寸也相同。这种概念验证并不是一个很好的解决方案,因为即使您更改红色面板,蓝色面板的首选尺寸也会固定。

也许更好的解决方案是使用Relative Layout。此布局将根据框架中可用的空间而不是首选尺寸来调整组件的大小,因此如果红色/蓝色面板具有相同的相对大小,即使添加了组件,它们也应该具有相同的大小。