如何将Swing中单列与两列布局的GUI合并为一个应用
Swing GUI合并与布局方案疑问
我已经开发了两个Swing GUI应用:一个采用单列布局,另一个采用两列布局,两款应用的截图如下:


问题
我希望把这两个GUI合并成一个应用。第二个应用基于GroupLayout实现,代码整洁且无需手动定位组件,但很多教程都指出GroupLayout并非合适选择,却没说明更优的布局方案。
第一款应用代码
public static void main(final String[] args) { SwingUtilities.invokeLater(Mvp::createGui); } private static void createGui() { final JFrame frame = new JFrame("Page labels app"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); final JPanel panel = new JPanel(new GridLayout(2, 1)); final JPanel tablePanel = createTablePanel(); panel.add(tablePanel); frame.add(panel, BorderLayout.CENTER); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } private static JPanel createTablePanel() { final PageLabelsTable table = new PageLabelsTable(); final JScrollPane scrollPane = new JScrollPane(table); scrollPane.setPreferredSize(new Dimension(400, 120)); final JPanel tablePanel = new JPanel(); tablePanel.add(scrollPane); tablePanel.setBorder(BorderFactory.createTitledBorder("Page styles")); return tablePanel; } public class PageLabelsTable extends JTable { private final DefaultTableModel tableModel; public PageLabelsTable() { tableModel = new DefaultTableModel(); tableModel.addColumn("Style"); tableModel.addColumn("Prefix"); tableModel.addColumn("From"); tableModel.addColumn("To"); tableModel.addRow( new String[]{"Table A 00", "Table A 01", "Table A 02", "Table A 03"}); tableModel.addRow( new String[]{"Table A 10", "Table A 11", "Table A 12", "Table A 13"}); setModel(tableModel); Toolkit.getDefaultToolkit().addAWTEventListener(event -> { if (event.getID() == MouseEvent.MOUSE_CLICKED) { final MouseEvent mouseEvent = (MouseEvent) event; final int row = rowAtPoint(mouseEvent.getPoint()); if (row == -1) { clearSelection(); } } }, AWTEvent.MOUSE_EVENT_MASK); getTableHeader().setReorderingAllowed(false); setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); setDragEnabled(true); } }
第二款应用代码
public void createUI() { initUI(); final JFrame frame = new JFrame(APP_NAME); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.setResizable(false); closeOnEscape(frame); frame.getRootPane().setDefaultButton(fixButton); frame.setContentPane(ui); frame.pack(); frame.setLocationRelativeTo(null); frame.setMinimumSize(frame.getSize()); frame.setVisible(true); } private void closeOnEscape(final JFrame frame) { // close on ESCAPE frame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW) .put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "Cancel"); frame.getRootPane().getActionMap().put("Cancel", disposeFrame(frame)); } private AbstractAction disposeFrame(final JFrame frame) { return new AbstractAction() { @Override public void actionPerformed(final ActionEvent e) { frame.dispose(); } }; } private JComponent getTwoColumnLayout(final JLabel[] labels, final JComponent[] fields) { if ( labels.length != fields.length ) { throw new IllegalArgumentException( "%d labels supplied for %d fields!".formatted(labels.length, fields.length)); } final JComponent panel = new JPanel(); final GroupLayout layout = new GroupLayout(panel); panel.setLayout(layout); // Turn on automatically adding gaps between components layout.setAutoCreateGaps(true); // Create a sequential group for the horizontal axis. final GroupLayout.SequentialGroup hGroup = layout.createSequentialGroup(); final GroupLayout.Group yLabelGroup = layout.createParallelGroup( GroupLayout.Alignment.TRAILING); hGroup.addGroup(yLabelGroup); final GroupLayout.Group yFieldGroup = layout.createParallelGroup(); hGroup.addGroup(yFieldGroup); layout.setHorizontalGroup(hGroup); // Create a sequential group for the vertical axis. final GroupLayout.SequentialGroup vGroup = layout.createSequentialGroup(); layout.setVerticalGroup(vGroup); // add the components to the groups for (JLabel label : labels) { yLabelGroup.addComponent(label); } for (Component field : fields) { yFieldGroup.addComponent(field, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE); } for (int i = 0; i < labels.length; i++) { vGroup.addGroup(layout.createParallelGroup().addComponent(labels[i]) .addComponent(fields[i], GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE)); } addMnemonics(labels, fields); return panel; } private void addMnemonics(final JLabel[] labels, final JComponent[] fields) { final Map<Character, Character> map = new HashMap<>(); for (int i = 0; i < labels.length; i++) { labels[i].setLabelFor(fields[i]); final String lowerCase = labels[i].getText().toLowerCase(); for (int j = 0; j < lowerCase.length(); j++) { final char ch = lowerCase.charAt(j); if ( Character.isLetterOrDigit(ch) && map.get(ch) == null ) { map.put(ch, ch); labels[i].setDisplayedMnemonic(ch); break; } } } } /** * Provides a JPanel with two columns (labels & fields) laid out using GroupLayout. The arrays * must be of equal size. * * @param labelStrings Strings that will be used for labels. * @param fields The corresponding fields. * @return JComponent A JPanel with two columns of the components provided. */ private JComponent getTwoColumnLayout(final String[] labelStrings, final JComponent[] fields) { final JLabel[] labels = new JLabel[labelStrings.length]; for (int i = 0; i < labels.length; i++) { labels[i] = new JLabel(labelStrings[i]); } return getTwoColumnLayout(labels, fields); } private void initUI() { if ( ui != null ) { return; } ui = new JPanel(new BorderLayout(4, 4)); ui.setBorder(new EmptyBorder(4, 4, 4, 4)); // Here is our control. This puts a titled border around it, // instead of using a label in the PAGE_START final JPanel jPanel = new JPanel(new BorderLayout()); ui.add(jPanel); final JPanel actionPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 15, 15)); jPanel.add(actionPanel, BorderLayout.PAGE_END); this.fixButton = new JButton("Fix"); this.resetButton = new JButton("Reset"); this.cancelButton = new JButton("Cancel"); Stream.of(fixButton, resetButton, cancelButton).forEach(actionPanel::add); // Use GroupLayout for the label/cotrnl combos. // make the arrays for the factory method final String[] labels = { "Page label style", "Start page", "Remove bookmarks" }; final String[] ccString = LabelStyle.getAllStyles(); final JPanel checkBoxPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0)); checkBoxPanel.add(new JCheckBox("", false)); final JComponent[] controls = { new JComboBox<>(ccString), new JTextFieldNumeric(5), checkBoxPanel }; jPanel.add(getTwoColumnLayout(labels, controls)); // throw in a few borders for white space final Border insideBorder = new CompoundBorder(new EmptyBorder(10, 10, 5, 10), new TitledBorder(APP_NAME)); final Border border = new CompoundBorder(insideBorder, new EmptyBorder(10, 10, 5, 10)); jPanel.setBorder(border); }
内容的提问来源于stack exchange,提问作者menteith
相关产品推荐
相关产品推荐

