簡體   English   中英

JPanel 和 JLabels 拉伸以適應父級的大小,無論最大大小如何 - java wordle clone

[英]JPanel and JLabels stretching to fit size of parent, regardless of maximum size - java wordle clone

在擴展 JFrame 的類中,我有以下代碼:

public Frame() {
        setTitle("WORDLE");

        // creates all containers
        Container mainContainer = getContentPane();
        JPanel gridContainer = new JPanel();
        JPanel optionsContainer = new JPanel();

        // sets size of main frame
        setSize(WIDTH, 900);

        // sets background size and background colors of all containers
        gridContainer.setBackground(GameTheme.BACKGROUND); // TODO: add message label inside of gridContainer below grid JPanel
        gridContainer.setPreferredSize(new Dimension(WIDTH - 150, 500));
        gridContainer.setMaximumSize(new Dimension(WIDTH - 150, 500));
        gridContainer.setLayout(new BorderLayout(10, 0));

        optionsContainer.setBackground(GameTheme.BACKGROUND);
        optionsContainer.setPreferredSize(new Dimension(WIDTH, 100));

        // creates grid with boxes for letter
        grid = new JPanel();
        grid.setLayout(new GridLayout(6, 5, 5, 5));

        grid.setPreferredSize(new Dimension(WIDTH - 150, 400));
        grid.setMaximumSize(new Dimension(WIDTH - 150, 400));

        grid.setBackground(GameTheme.BACKGROUND);
        createBoxes();

        // JLabel for messages
        JLabel alertLabel = new JLabel("test");
        alertLabel.setOpaque(true);
        alertLabel.setForeground(GameTheme.WHITE);
        alertLabel.setBackground(GameTheme.BACKGROUND);

        // listens for presses in the JFrame, with the Game class implementing the method for the keypress event
        addKeyListener(new Game(boxes));

        // lays out all containers and their sub-containers
        // title label at top, grid container at center, options container at bottom
        mainContainer.setLayout(new BorderLayout());
        mainContainer.add(createTitle(), BorderLayout.NORTH); // createTitle returns a JLabel
        mainContainer.add(gridContainer, BorderLayout.CENTER);
        mainContainer.add(optionsContainer, BorderLayout.SOUTH);
        gridContainer.add(grid, BorderLayout.NORTH);
        gridContainer.add(alertLabel, BorderLayout.SOUTH);

        // boilerplate frame configuration
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(false);
        setLocationRelativeTo(null);
        pack();
        setVisible(true);
}

public void createBoxes() {
        // initializes 2d array for letter boxes
        boxes = new LetterBox[6][5];

        // populates 2d array and adds boxes to the grid container
        for (int r = 0; r < 6; r++) {
            for (int c = 0; c < 5; c++) {
                LetterBox letterBox = new LetterBox(r, c);
                boxes[r][c] = letterBox;
                grid.add(letterBox.getBox());
            }
        }
}

我在gridContainer中的所有組件上設置了最大尺寸,甚至在gridContainer本身上設置了最大尺寸,但 JLabels 仍在拉伸以占用 GUI 的尺寸。 有人可以幫我弄清楚為什么會這樣,我該如何解決?

為了讓問題更清楚,這里有一些圖像顯示了我想要的和我得到的:

預期的: 預期結果

實際的: 實際結果

我試圖盡可能清楚地描述,請發表評論並讓我知道是否有任何需要澄清的地方。

不要一直使用父面板和框架的首選/最小/最大尺寸。 每個面板應該能夠根據添加到面板的組件的首選尺寸來計算其首選尺寸。 因此,您將組件添加到面板並將面板添加到框架,然后打包框架,所有內容都將以適當的尺寸顯示。

因此,在您的情況下,您可以為“gridContainer”使用GridLayout 然后將 JLabels 添加到 gridContainer。 對於您的 LetterBox 組件,您應該使用“等寬”字體,以便所有字符占用相同的空間。 然后你可以用默認值“”初始化你的標簽,給標簽一個大小。

這個尺寸太小了,所以你還想給LetterBox添加一個EmptyBorder 因此,在構造函數中,您可以添加如下內容:

setBorder( new EmptyBorder(10, 10, 10, 10) );

現在,LeterBox 可以正確計算其首選大小,並且“gridContainer”將能夠正確計算其首選大小。

但是,當您將面板添加到 BorderLayout 的 CENTER 時,BorderLayout 將嘗試調整每個組件的大小以填充框架中的可用空間。 為了防止這種情況,您可以使用“包裝器”面板:

JPanel wrapper = new JPanel(); // uses FlowLayout by default
wrapper.add( gridContainer );
mainContainer.add(wrapper, BorderLayout.CENTER);
//mainContainer.add(gridContainer, BorderLayout.CENTER);

現在,如果調整框架的大小,額外的空間將進入包裝面板而不是 gridContainer。

如果您想稍微放寬框架不可調整大小的要求,請遵循一些將網格的最大大小限制為首選但不限制最小值的實現。 因此,在這兩種實現中,網格都不會大於其首選大小,從而使用戶可以放大框架和空白空間,以便LayoutManager出現用於填充剩余空間的空間。

然而,網格的最小尺寸不受限制,以防萬一用戶想要將框架調整為更小的尺寸。 這應該是一個額外的功能,但如果你想禁用它,最簡單的方法是取消注釋frame.setMinimumSize(frame.getSize()); 每個實現中的行。

兩種實現都考慮了網格的大小。

BoxLayout實現:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class BoxMain {
    
    private static void createAndShowGUI() {
        final int rows = 6, cols = 15;
        final JPanel grid = new JPanel(new GridLayout(rows, 0, 5, 5));
        for (int row = 0; row < rows; ++row)
            for (int col = 0; col < cols; ++col)
                grid.add(new JLabel(Integer.toString(row * cols + col), JLabel.CENTER));
        final Dimension sz = grid.getPreferredSize();
        grid.setMaximumSize(sz);
        grid.setMinimumSize(new Dimension(0, sz.height));
        
        final JPanel box = new JPanel();
        box.setLayout(new BoxLayout(box, BoxLayout.X_AXIS));
        box.add(Box.createGlue());
        box.add(grid);
        box.add(Box.createGlue());
        
        final JPanel mainPanel = new JPanel(new BorderLayout());
        mainPanel.add(box, BorderLayout.CENTER);
        mainPanel.add(new JLabel("Alert label", JLabel.CENTER), BorderLayout.PAGE_END);
        
        final JFrame frame = new JFrame("Wordle");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        //frame.setMinimumSize(frame.getSize());
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
    
    public static void main(final String[] args) {
        SwingUtilities.invokeLater(BoxMain::createAndShowGUI);
    }
}

SpringLayout實現:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Spring;
import javax.swing.SpringLayout;
import javax.swing.SwingUtilities;

public class SpringMain {
    
    private static void createAndShowGUI() {
        final int rows = 6, cols = 15;
        final JPanel grid = new JPanel(new GridLayout(rows, 0, 5, 5));
        for (int row = 0; row < rows; ++row)
            for (int col = 0; col < cols; ++col)
                grid.add(new JLabel(Integer.toString(row * cols + col), JLabel.CENTER));
        grid.setMaximumSize(grid.getPreferredSize());
        grid.setMinimumSize(new Dimension());
        
        final SpringLayout layout = new SpringLayout();
        final JPanel spring = new JPanel(layout);
        spring.add(grid);
        final Spring flexible = Spring.constant(0, 0, Short.MAX_VALUE);
        layout.putConstraint(SpringLayout.WEST, grid, flexible, SpringLayout.WEST, spring);
        layout.putConstraint(SpringLayout.EAST, spring, flexible, SpringLayout.EAST, grid);
        layout.putConstraint(SpringLayout.NORTH, grid, flexible, SpringLayout.NORTH, spring);
        layout.putConstraint(SpringLayout.SOUTH, spring, flexible, SpringLayout.SOUTH, grid);
        
        final JPanel mainPanel = new JPanel(new BorderLayout());
        mainPanel.add(spring, BorderLayout.CENTER);
        mainPanel.add(new JLabel("Alert label", JLabel.CENTER), BorderLayout.PAGE_END);
        
        final JFrame frame = new JFrame("Wordle");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        //frame.setMinimumSize(frame.getSize());
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
    
    public static void main(final String[] args) {
        SwingUtilities.invokeLater(SpringMain::createAndShowGUI);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM