如何让 TitledBorder 的标题在 GUI 中正确显示

How to get the TitledBorder's title to display properly in the GUI

除了一件事,我的 GUI 大部分都能正常显示。 TitledBorder("Numeric Type") 不显示右侧 JPanel 的整个标题。我相信它与 BorderLayout 管理器有关。而不是在边框内显示 "Numeric Type",只显示 "Numeric..."。任何帮助将不胜感激。

public class P3GUI extends JFrame {

    private JLabel originalList;
    private JTextField originalSort;
    private JLabel sortedList;
    private JTextField newSort;
    private JPanel panel;
    private JButton performSort;
    private JRadioButton ascending;
    private JRadioButton descending;
    private ButtonGroup sort;
    private JRadioButton integer;
    private JRadioButton fraction;
    private ButtonGroup numType;
    private JPanel inputPanel, outputPanel, calculatePanel, radioPanel;
    private JPanel left, right;

    public P3GUI () {
        super("Binary Search Tree Sort");
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        originalList = new JLabel("Original List");
        originalSort = new JTextField(20);        
        inputPanel = new JPanel();
        inputPanel.add(originalList);
        inputPanel.add(originalSort);
        sortedList = new JLabel("Sorted List");
        newSort = new JTextField(20);
        newSort.setEditable(false);
        outputPanel = new JPanel();
        outputPanel.add(sortedList);
        outputPanel.add(newSort);
        panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
        panel.add(inputPanel);
        panel.add(outputPanel);
        add(panel, BorderLayout.NORTH);
        performSort = new JButton("Perform Sort");
        calculatePanel = new JPanel();
        calculatePanel.add(performSort);
        add(calculatePanel, BorderLayout.CENTER);        
        ascending = new JRadioButton("Ascending");
        descending = new JRadioButton("Descending");
        sort = new ButtonGroup();
        sort.add(ascending);
        sort.add(descending);
        integer = new JRadioButton("Integer");
        fraction = new JRadioButton("Fraction");
        numType = new ButtonGroup();
        numType.add(integer);
        numType.add(fraction);
        radioPanel = new JPanel();
        radioPanel.setLayout(new FlowLayout());
        left = new JPanel();
        left.setLayout(new GridLayout(2,1));
        left.setBorder(BorderFactory.createTitledBorder("Sort Order"));
        left.add(ascending);
        left.add(descending);
        right = new JPanel();
        right.setLayout(new GridLayout(2,1));
        right.setBorder(BorderFactory.createTitledBorder("Numeric Type"));
        right.add(integer);
        right.add(fraction);
        radioPanel.add(left);
        radioPanel.add(right);
        add(radioPanel, BorderLayout.SOUTH);        
        pack();

    }
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                new P3GUI().setVisible(true);
            }
        });
    }

}

问题是右侧 JPanel 太小,无法显示整个标题,因此被截断了。我建议将底部的两个 JPanel 放入另一个使用 GridLayout 的 JPanel 中,然后将它们以展开的方式放置以适合 GUI 的底部。当展开时,标题有更大的机会被完全显示(但不是保证,请注意!)。

例如,如果您让主 GUI 使用 BorderLayout,并将使用 JPanelGridLayout 添加到 BorderLayout.CENTER 位置,它将完全填充.然后可以将顶部组件 TextFields 和 JButton 添加到另一个 JPanel,比如使用 GridBagLayout 的组件,并将其添加到主要 JPanelBorderLayout.PAGE_START位置。

例如,以下代码生成此 GUI:

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.KeyEvent;
import javax.swing.*;

@SuppressWarnings("serial")
public class P3GUI2 extends JPanel {
    private static final int COLS = 20;
    private JTextField originalSort = new JTextField(COLS);
    private JTextField newSort = new JTextField(COLS);
    private JButton performSort = new JButton("Perform Sort");
    private JRadioButton ascending = new JRadioButton("Ascending");
    private JRadioButton descending = new JRadioButton("Descending");
    private ButtonGroup sort = new ButtonGroup();
    private JRadioButton integer = new JRadioButton("Integer");
    private JRadioButton fraction = new JRadioButton("Fraction");
    private ButtonGroup numType = new ButtonGroup();

    public P3GUI2() {
        JPanel topPanel = new JPanel(new GridBagLayout());
        topPanel.add(new JLabel("Original List:"), createGbc(0, 0));
        topPanel.add(originalSort, createGbc(1, 0));
        topPanel.add(new JLabel("Sorted List:"), createGbc(0, 1));
        topPanel.add(newSort, createGbc(1, 1));

        performSort.setMnemonic(KeyEvent.VK_P);
        JPanel btnPanel = new JPanel();
        btnPanel.add(performSort);

        JPanel sortOrderPanel = createTitlePanel("Sort Order");
        JPanel numericPanel = createTitlePanel("Numeric Type");

        sortOrderPanel.add(ascending);
        sortOrderPanel.add(descending);
        sort.add(ascending);
        sort.add(descending);

        numericPanel.add(integer);
        numericPanel.add(fraction);
        numType.add(integer);
        numType.add(fraction);

        JPanel radioPanels = new JPanel(new GridLayout(1, 0, 3, 3));
        radioPanels.add(sortOrderPanel);
        radioPanels.add(numericPanel);        

        setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
        setLayout(new BorderLayout(3, 3));
        add(topPanel, BorderLayout.PAGE_START);
        add(btnPanel, BorderLayout.CENTER);
        add(radioPanels, BorderLayout.PAGE_END);
    }

    private JPanel createTitlePanel(String title) {
        JPanel panel = new JPanel(new GridLayout(0, 1, 3, 3));
        panel.setBorder(BorderFactory.createTitledBorder(title));
        return panel;
    }

    private GridBagConstraints createGbc(int x, int y) {
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = x;
        gbc.gridy = y;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.anchor = x == 0 ? GridBagConstraints.WEST : GridBagConstraints.EAST;
        gbc.insets = new Insets(3, 3, 3, 3);
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;
        return gbc;
    }

    private static void createAndShowGui() {
        P3GUI2 mainPanel = new P3GUI2();

        JFrame frame = new JFrame("Binary Search Tree Sort");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

或者您可以将上面的 btnPanel 放入主面板 BorderLayout.CENTER,然后将 radioPanel 放入主面板 BorderLayout.PAGE_END。这将显示相​​同外观的 GUI,但如果 re-sized,它将展开不同。

面板的首选大小(由布局管理器确定)不考虑 TitledBorder 中文本的大小,因此标题可能会被截断。

这是一个可以与 TitleBorder 一起使用的自定义 JPanel。 getPreferredSize() 方法已自定义为使用最大宽度:

  1. 默认的getPreferredSize()计算
  2. TitledBorder 中文本的宽度

这是一个简单的例子:

import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;

public class TitledBorderPanel extends JPanel
{
    /**
     ** The preferred width on the panel must consider the width of the text
     ** used on the TitledBorder
     */
    @Override
    public Dimension getPreferredSize()
    {
        Dimension preferredSize = super.getPreferredSize();

        Border border = getBorder();
        int borderWidth = 0;

        if (border instanceof TitledBorder)
        {
            Insets insets = getInsets();
            TitledBorder titledBorder = (TitledBorder)border;
            borderWidth = titledBorder.getMinimumSize(this).width + insets.left + insets.right;
        }

        int preferredWidth = Math.max(preferredSize.width, borderWidth);

        return new Dimension(preferredWidth, preferredSize.height);
    }

    private static void createAndShowGUI()
    {
        JPanel panel = new TitledBorderPanel();
        panel.setBorder( BorderFactory.createTitledBorder("File Options Command List:") );
        panel.setLayout( new BoxLayout(panel, BoxLayout.Y_AXIS) );
        panel.add( new JLabel("Open") );
        panel.add( new JLabel("Close") );
//      panel.add( new JLabel("A really wierd file option longer than border title") );

        JFrame frame = new JFrame("TitledBorderPanel");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add( panel );
        frame.setLocationByPlatform( true );
        frame.pack();
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater( () -> createAndShowGUI() );
/*
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowGUI();
            }
        });
*/
    }
}