是否可以选择在不禁用 CardLayout 的情况下添加 ScrollPane?

Is there an option to add ScrollPane without disabling CardLayout?

我有一个卡片布局,我用一个按钮切换面板。但是,代码(切换面板)仅在行时有效:

    JScrollPane scrPane = new JScrollPane(card1);
    frame.add(scrPane);

已删除。在其他情况下,单击按钮没有任何效果。是否有一个选项可以保持滚动(我需要这个,因为主应用程序会有很多换行的文本)而不禁用切换卡片的选项?

package com.code;

import javax.swing.*;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.awt.event.*;

public class Card {

    public static void main(String[] args) {

        JFrame frame = new JFrame("App");
        frame.setVisible(true);
        frame.setSize(1200, 800);//Give it a size
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JPanel mainPanel = new JPanel(new CardLayout());
        frame.add(mainPanel);

        JPanel menu = new JPanel(new FlowLayout(FlowLayout.LEFT));
        JPanel card1 = new JPanel(new FlowLayout(FlowLayout.LEFT));
        JPanel card2 = new JPanel(new FlowLayout(FlowLayout.LEFT));

        mainPanel.add(menu, "menu");
        mainPanel.add(card1, "card1");
        mainPanel.add(card2, "card2");

        JLabel l1 = new JLabel("label 1");
        JLabel l2 = new JLabel("label 2");
        card1.add(l1);
        card2.add(l2);
        JButton click = new JButton("Click!");
        menu.add(click);

        JScrollPane scrPane = new JScrollPane(card1);
        frame.add(scrPane);

        click.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                CardLayout cardLayout = (CardLayout) mainPanel.getLayout();
                cardLayout.show(mainPanel, "card1");
            }
        });

    }

}

A JFrame(其内容窗格)默认为 uses BorderLayout。这意味着您在 BorderLayout.CENTER 处只能有 1 个组件。当您 frame.add(component) 时,默认约束是 BorderLayout.CENTER.

现在,你 frame.add(mainPanel); 然后 frame.add(scrPane);。因此删除了主面板,因为在它之后添加了 scrPane。

执行 JScrollPane scrPane = new JScrollPane(card1); 这意味着您将滚动窗格添加到 card1,而不是在内容窗格中。我想您希望它出现在内容窗格(整个框架)中。所以解决方法是删除 frame.add(mainPanel); 并执行以下操作:

JScrollPane scrPane = new JScrollPane(mainPanel);
frame.add(scrPane);

现在,主面板已添加到 scrPanescrPane 已添加到框架。

但是,在那之后您的 GUI 将是空的,因为您 frame.setVisible(true); 在完成向其添加组件之前。看看Why shouldn't I call setVisible(true) before adding components?

最终,完整代码为:

public static void main(String[] args) {
    SwingUtilities.invokeLater(() -> {
        JFrame frame = new JFrame("App");

        frame.setSize(1200, 800);//Give it a size
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JPanel mainPanel = new JPanel(new CardLayout());

        JPanel menu = new JPanel(new FlowLayout(FlowLayout.LEFT));
        JPanel card1 = new JPanel(new FlowLayout(FlowLayout.LEFT));
        JPanel card2 = new JPanel(new FlowLayout(FlowLayout.LEFT));

        mainPanel.add(menu, "menu");
        mainPanel.add(card1, "card1");
        mainPanel.add(card2, "card2");

        JLabel l1 = new JLabel("label 1");
        JLabel l2 = new JLabel("label 2");
        card1.add(l1);
        card2.add(l2);
        JButton click = new JButton("Click!");
        menu.add(click);

        JScrollPane scrPane = new JScrollPane(mainPanel);
        frame.add(scrPane);

        click.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                CardLayout cardLayout = (CardLayout) mainPanel.getLayout();
                cardLayout.show(mainPanel, "card1");
            }
        });
        frame.setVisible(true);
    });
}

我建议您阅读的一些不错的链接是 the Initial Threads and What does .pack() do?