【问题标题】:java GUI layout suggestionjava GUI布局建议
【发布时间】:2018-02-07 14:47:45
【问题描述】:
public class AFS {
    public JPanel afs(final Fields input){
        JPanel titlePanel = new JPanel();

        //Title fields
        JLabel afs = new JLabel("Statement", Label.LEFT);

        Label mm = new Label("month ", Label.LEFT);
        Label my = new Label("Year ", Label.LEFT);

        //first line
        titlePanel.add(afs);
        titlePanel.add(mm);
        titlePanel.add(input.MENTRY);
        titlePanel.add(my);
        titlePanel.add(input.YENTRY);
        titlePanel.setPreferredSize(null);

        //Left Panels
        JPanel sb = new JPanel();
        JPanel entry = new JPanel();
        entry.setLayout(new BoxLayout(entry, BoxLayout.Y_AXIS));
        entry.setAlignmentX(Component.LEFT_ALIGNMENT);
        entry.add(new Label("Service "));
        entry.add(input.s);
        entry.add(new Label("Amount "));
        entry.add(input.a);
        entry.add(new Label("Counter "));
        entry.add(input.o);
        entry.add(new Label("Division "));
        entry.add(input.d);

        sb.add(entry);


        JPanel holderPanel = new JPanel();
        holderPanel.setLayout(new BoxLayout(holderPanel, BoxLayout.Y_AXIS));
        holderPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
        holderPanel.add(titlePanel);
        holderPanel.add(sb);

        JButton start = new JButton("Save Current");
        start.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                ScriptAction action = new ScriptAction();
                action.saveAll(input,1);
            }
        });
        holderPanel.add(start); 
        return holderPanel;
    }

我有上面代码的简短版本。 当前布局如下所示:

但我希望布局看起来像(油漆编辑)。

我已经尝试使用 gridLayout 作为条目进行交换,它会显示 2 行,但 gridlayout 仍会在中心对齐所有内容(包括标题和标题)。此外,按钮跨度将跨越整个底部。我想知道是否有任何建议的方法来做到这一点?

【问题讨论】:

  • 使用GridBagLayout卢克。或自定义LayoutManager,如MigLayoutFormLayout
  • 也不要混用轻量级和重量级的组件。始终使用带有“J”前缀的组件。 JLabel(非Label)、JTextField(非TextField)等

标签: java swing user-interface layout-manager


【解决方案1】:

您需要使用layout managers 的组合来实现所需的输出:

调整大小前/调整大小后

在这种情况下,有 3 个主要部分:

  • 顶部窗格(使用Box 对齐左侧的一些文本和右侧的一些文本)
  • 中间窗格(使用GridBagLayout 来定位图像中的组件,也许GridLayout 带有适当的插图也可以工作)
  • 底部窗格(使用默认 JPanel 的布局:FlowLayout

顶部窗格也使用 2 个 JPanels,第一个用于标签 Statement,其他 4 个组件与 FlowLayout 右侧对齐,根据 this answer BoxLayout 确实不尊重我们JTextFields 的首选大小。因此,一种解决方法是将它们包装在另一个 JPanel 中,然后将 JPanelStatement 标签一起包装。

中间窗格也出现了类似的问题,它需要使用 2 个JPanels:一个用于包裹在另一个更大的包含它的字段中,JButton 在底部 (Save Current)。我们可以通过将JButtongridx = 2gridy = 2counterdivision 标签和gridx = 3gridx = 4 上的字段分别添加(而不是2 & 3)来实现类似的输出,但是然后,我们需要添加 gbc.insets 以在顶部和底部添加具有高值的插图...由您决定使用哪一个 :)

产生上述输出的代码如下:

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class FormSample {
    private JFrame frame;
    private JPanel topRightPane;
    private JPanel centerPane;
    private JPanel centerWithButtonPane;
    private JPanel buttonsPane;

    private JTextField monthField;
    private JTextField yearField;

    private JTextField serviceField;
    private JTextField amountField;
    private JTextField counterField;
    private JTextField divisionField;

    private static final int LEFT_MARGIN = 50; //Increase / Decrease to add extra space between components
    private static final int RIGHT_MARGIN = LEFT_MARGIN;

    //Change insets accordingly to add extra space between components (top, left, bottom, right)
    private static final Insets leftInsets = new Insets(0, LEFT_MARGIN, 0, 0);
    private static final Insets rightInsets = new Insets(0, 0, 0, RIGHT_MARGIN);
    private static final Insets defaultInsets = new Insets(0, 0, 0, 0);

    private JButton saveCurrentButton;
    private JButton saveAllButton;
    private JButton resetButton;

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

    private void createAndShowGui() {
        frame = new JFrame(getClass().getSimpleName());

        monthField = new JTextField(10);
        yearField = new JTextField(10);

        serviceField = new JTextField(10);
        amountField = new JTextField(10);
        counterField = new JTextField(10);
        divisionField = new JTextField(10);

        saveCurrentButton = new JButton("Save Current");
        saveAllButton = new JButton("Save all");
        resetButton = new JButton("Reset");

        buttonsPane = new JPanel();

        topRightPane = new JPanel();
        topRightPane.setLayout(new FlowLayout(FlowLayout.RIGHT));

        topRightPane.add(new JLabel("Month"));
        topRightPane.add(monthField);
        topRightPane.add(new JLabel("Year"));
        topRightPane.add(yearField);

        centerWithButtonPane = new JPanel();
        centerWithButtonPane.setLayout(new BoxLayout(centerWithButtonPane, BoxLayout.PAGE_AXIS));

        Box box = Box.createHorizontalBox();
        box.add(new JLabel("Statement"));
        box.add(Box.createHorizontalGlue());
        box.add(topRightPane);

        centerPane = new JPanel();
        centerPane.setLayout(new GridBagLayout());

        GridBagConstraints gbc = new GridBagConstraints();

        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.insets = defaultInsets;
        centerPane.add(new JLabel("Service"), gbc);

        gbc.gridx = 1;
        gbc.insets = rightInsets;
        centerPane.add(serviceField, gbc);

        gbc.gridx = 2;
        gbc.insets = leftInsets;
        centerPane.add(new JLabel("Counter"), gbc);

        gbc.gridx = 3;
        gbc.insets = defaultInsets;
        centerPane.add(counterField, gbc);

        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.insets = defaultInsets;
        centerPane.add(new JLabel("Amount"), gbc);

        gbc.gridx = 1;
        gbc.insets = rightInsets;
        centerPane.add(amountField, gbc);

        gbc.gridx = 2;
        gbc.insets = leftInsets;
        centerPane.add(new JLabel("Division"), gbc);

        gbc.gridx = 3;
        gbc.insets = defaultInsets;
        centerPane.add(divisionField, gbc);

        saveCurrentButton.setAlignmentX(Component.CENTER_ALIGNMENT); //Force centered alignment for our JButton
        centerWithButtonPane.add(centerPane);
        centerWithButtonPane.add(saveCurrentButton);

        buttonsPane.add(saveAllButton);
        buttonsPane.add(resetButton);

        frame.add(box, BorderLayout.NORTH);
        frame.add(centerWithButtonPane, BorderLayout.CENTER);
        frame.add(buttonsPane, BorderLayout.SOUTH);
        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

另外请遵循@SergiyMedvynskyy 给出的建议,不要混合 AWT 和 Swing 组件(即 JTextFieldTextField),并且只使用 Swing 组件,因为 AWT 有问题。

【讨论】:

  • 解释得很好。谢谢
猜你喜欢
  • 2011-09-12
  • 1970-01-01
  • 2018-05-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-11
相关资源
最近更新 更多