JPanels:Java 世界的 <div>?

JPanels: the <div>s of the Java world?

JPanel 是否可以像 <div> 在 HTML 中使用一样在 Java 中使用?除了 CardLayout 之外,在 JFrame 中拥有超过 1 个 JPanel 是否符合良好实践? (例如,如果我的 JPanel 包含一个 help/about 按钮,该按钮位于 JFrame 的内容面板的北边界上,并且我使用包含该按钮的按钮来放置一些间距以强制按钮一定大小...)

具体案例:

假设我正在尝试这样做:, and upon starting, I have a mock like this (thanks to some code for the button rendering I found elsewhere): 。这种情况是否适合使用多个 JFrames(就像那些 HTML <div>s 一样)?如果没有,什么时候会?

根据您的要求,您“不必”使用多个面板,您可以通过一个面板和一个 GridBagLayout 来完成您想要的,例如...

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            JButton helpButton = new JButton("?");
            JTextField projectDirectory = new JTextField(20);
            JTextField documentDirectory = new JTextField(20);
            JButton projectButton = new JButton("Project");
            JButton documentButton = new JButton("Document");
            JButton continueButton = new JButton("Continue to files");

            setLayout(new GridBagLayout());

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 1;

            add(new JLabel("Project Directory"), gbc);
            gbc.gridy++;
            add(new JLabel("Documentation Directory"), gbc);

            gbc.gridx = 1;
            gbc.gridy = 1;
            add(projectDirectory, gbc);
            gbc.gridy++;
            add(documentDirectory, gbc);

            gbc.gridx = 2;
            gbc.gridy = 0;
            add(helpButton, gbc);
            gbc.gridy++;
            add(projectButton, gbc);
            gbc.gridy++;
            add(documentButton, gbc);

            gbc.gridx = 0;
            gbc.gridy++;
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            add(continueButton, gbc);
        }

    }

}

我使用多个面板的主要原因是:

  1. 布局过于复杂,可以让我将布局分解为单独的需求,并更多地关注组之间的关系
  2. 如果我专注于将管理分离成单独的元素(例如目录选择),那么面板可以成为一个独立的工作单元,包括管理和功能,允许成为一个独立的和可重复使用的组件

复合面板...

import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            JButton helpButton = new JButton("?");
            JButton continueButton = new JButton("Continue to files");

            setLayout(new GridBagLayout());

            GridBagConstraints gbc = new GridBagConstraints();

            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.anchor = GridBagConstraints.EAST;
            add(helpButton, gbc);

            gbc.gridy++;
            add(new FolderSelectionPane("Project Folder"), gbc);
            gbc.gridy++;
            add(new FolderSelectionPane("Documentation Folder"), gbc);
            gbc.anchor = GridBagConstraints.CENTER;
            gbc.gridy++;
            add(continueButton, gbc);
        }

    }

    public class FolderSelectionPane extends JPanel {

        public FolderSelectionPane(String label) {
            JTextField projectDirectory = new JTextField(20);
            JButton projectButton = new JButton("Folder");

            setLayout(new GridBagLayout());

            GridBagConstraints gbc = new GridBagConstraints();

            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.insets = new Insets(0, 2, 0, 2);
            add(new JLabel(label), gbc);

            gbc.gridx++;
            add(projectDirectory, gbc);

            gbc.gridx++;
            add(projectButton, gbc);
        }

    }

}