一个JPanel内部的JPanel如何添加JScrollPane

4

阅读这篇答案后,我决定使用getPreferredSize而不是setPreferredSize。但我仍然无法使用@Override getPreferredSize,但这目前不是我面临的主要问题。

我有一个CardLayout应用程序,调用一个名为HiraganaData的类

HiraganaData是一个扩展了JPanel的类,以便可以被CardLayout使用,但它还有另外两个JPanel,一个用于“返回”按钮,另一个用于其余的按钮,在使用这个想法之前,我正在使用JTable,但在将单元格制作为按钮时遇到了问题,所以我放弃了这个想法,并提出了这个新想法,使用GridLayout。其中一些按钮将被禁用,不管怎样我都可以做到这一点,并且不会包含那段代码,因为它与问题无关。

因此,我的实际问题或问题是:

  • 如何将JScrollPane 添加到buttonsPanel,我尽了最大努力,甚至将其添加到整个“全局”面板中都没有成功。

这是我可以用我的类的相同代码做出的最接近GUI。

不确定是否相关,但我正在使用具有不同大小的CardLayout,方式是在此答案中由@MadProgrammer建议的方式。

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.*;
import javax.swing.table.TableCellRenderer;
import javax.swing.DefaultCellEditor;
import java.awt.Dimension;

public class HiraganaPage extends JPanel {
    JFrame frame = new JFrame("Hello");
    JButton kanas[][] = new JButton[26][5];
    JButton backButton = new JButton("back");
    JPanel backPanel = new JPanel();
    JPanel buttonsPanel = new JPanel();
    
    public static void main(String args[]) {
        new HiraganaPage();
    }
    
    public HiraganaPage() {
        JPanel pane = new JPanel();
        backPanel.add(backButton);
        buttonsPanel.setLayout(new GridLayout(0, 5));
        pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));
        pane.add(backPanel);
        
        //pane.setPreferredSize(new Dimension(500, 500));
        
        for (int i = 0; i < 26; i++) {
            for (int j = 0; j < 5; j++) {
                kanas[i][j] = new JButton("1");
                buttonsPanel.add(kanas[i][j]);
            }
        }
        
        JScrollPane scroll = new JScrollPane(buttonsPanel);
        pane.add(buttonsPanel);
        this.add(pane, BorderLayout.CENTER);
        frame.add(this);
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocation(50, 50);
        frame.setSize(300, 300);
    }
}

这是在我的完整应用程序中的外观。 enter image description here 而这是在MCVE中的外观。 enter image description here

2
简短的回答是,不要改变面板的首选大小... - MadProgrammer
@MadProgrammer,你是指pane.setPreferredSize(new Dimension(500, 500));这一行吗?注释掉了,看起来更好了,但滚动条也不会出现。 - Frakcool
检查答案,你实际上没有向滚动窗格添加任何内容,也没有将滚动窗格添加到任何东西中...按照惯例,应始终避免使用setPreferred/Minimum/MaximumSize,因为它会引起更多问题而不是解决问题,而是覆盖所需的适当方法。 - MadProgrammer
MCVE,清晰的问题描述,研究证据,两个相关的截图。+1(千)。好问题。 - Andrew Thompson
1
哦,谢谢@AndrewThompson,我在这里看到像你、MadProgrammer、Kleopatra、thrashgod和其他几个人一样的人,我很想成为像你们一样优秀的人。我总是看到你们所有人的答案,这让我在每个问题和回答上都更加努力。 - Frakcool
1
很高兴看到你的努力得到了@MadProgrammer的快速回答。 :) - Andrew Thompson
1个回答

4
你面临的主要问题是,当你将buttonsPane添加到pane中时,将其从滚动窗格中移除了...
JScrollPane scroll = new JScrollPane(buttonsPanel);
pane.add(buttonsPanel);
this.add(pane, BorderLayout.CENTER);

而你从未将滚动面板添加到任何东西中去,这也没有帮助。
一个组件只能有一个父级,所以当你把buttonsPane添加到pane时,它实际上已经从滚动面板中移除了。
相反,将HiraganaPage的布局管理器设置为BorderLayout,将buttonsPanel添加到滚动面板中,并将滚动面板添加到HiraganaPageCENTER位置,然后将pane添加到HiraganaPageNORTH位置。

Buttons

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestScrollPane {

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

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

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

    public class HiraganaPage extends JPanel {

        JFrame frame = new JFrame("Hello");
        JButton kanas[][] = new JButton[26][5];
        JButton backButton = new JButton("back");
        JPanel backPanel = new JPanel();
        JPanel buttonsPanel = new JPanel();

        public HiraganaPage() {
            setLayout(new BorderLayout());

            JPanel pane = new JPanel();
            backPanel.add(backButton);
            buttonsPanel.setLayout(new GridLayout(0, 5));
            pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));
            pane.add(backPanel);

//            pane.setPreferredSize(new Dimension(500, 500));

            for (int i = 0; i < 26; i++) {
                for (int j = 0; j < 5; j++) {
                    kanas[i][j] = new JButton("1");
                    buttonsPanel.add(kanas[i][j]);
                }
            }

            add(pane, BorderLayout.NORTH);
            add(new JScrollPane(buttonsPanel));
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(500, 500);
        }
    }

}

是的,我也注意到了在我编辑帖子时滚动条的那一部分......但父级的部分很有趣......现在我看到了你如何使用@Override部分,我之前用的方法是错误的(在构造函数中而不是作为方法)。让我仔细分析一下。 - Frakcool
谢谢,我知道这很简单,但即使做了MCVE也没有注意到滚动条的添加。您通过此解决了我多个问题 :) - Frakcool

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接