【问题标题】:How to make scrollable JPanel displaying JLabels如何使可滚动的 JPanel 显示 JLabels
【发布时间】:2019-04-20 17:35:27
【问题描述】:

我有一个JLabels 的列表,它们是 280 x 50 并包含文本。我想创建 280 x 300 JPanel,添加所有标签并使其可滚动(因为我们可以有超过 6 个标签)。

我不知道如何将超过 6 个标签添加到此特定大小的面板,也不知道如何使其可滚动(我尝试将面板添加到相同大小的 JScrollPane,但实际上没有发生任何事情)。有没有办法做到这一点?

【问题讨论】:

  • 首先,不要再纠结容器的大小了。容器的大小需要根据它的内容动态计算,只有这样JScrollPane才能工作
  • 我确实想知道在 JScrollPane 中保存的 JList 是否是您真正需要的。 JList 可以像 JLabels 网格一样工作,但效率更高。

标签: java swing jpanel jlabel jscrollpane


【解决方案1】:

首先,不要再乱搞组件的大小了。 Swing 已经有一个非常强大的布局管理器 API,它考虑了 GUI 框架和平台和硬件差异的许多不同方面,让它发挥作用。

JScrollPane 取决于它的内容是否能够独立于JScrollPane 的大小来计算它的大小,只有这样它才能决定何时应该显示滚动条。这也适用于JPanel。它的大小应根据其内容的总要求来计算。奇怪的是,如果您使用布局管理器 API,所有这些都是免费的。

所以,一个快速的讨厌的例子可能看起来像......

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
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 JScrollPane(new TestPane()));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            for (int index = 0; index < 600; index++) {
                JLabel label = new JLabel("This is test " + index);
                // This is for demonstration purposes only
                // you should let the lable calculate its size based on its text
                // and image properties
                label.setPreferredSize(new Dimension(280, 50));
                add(label, gbc);
            }
        }

    }
}

但是窗口太长了!

因此,这变得稍微复杂一些。您需要能够向JScrollPane 提供有关您希望组件大小的其他提示。为此,有Scrollable...

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.Scrollable;
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 JScrollPane(new TestPane()));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel implements Scrollable {

        public TestPane() {
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;
            for (int index = 0; index < 600; index++) {
                JLabel label = new JLabel("This is test " + index);
                // This is for demonstration purposes only
                // you should let the lable calculate its size based on its text
                // and image properties
                label.setPreferredSize(new Dimension(280, 50));
                add(label, gbc);
            }
        }

        @Override
        public Dimension getPreferredScrollableViewportSize() {
            return new Dimension(290, 300);
        }

        @Override
        public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
            return 128;
        }

        @Override
        public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
            return 128;
        }

        @Override
        public boolean getScrollableTracksViewportWidth() {
            return true;
        }

        @Override
        public boolean getScrollableTracksViewportHeight() {
            return true;
        }

    }
}

但是……

这一切都提出了一个问题,为什么?为什么不直接使用 JList 或 JTable,它们已经完成了所有这些工作?

【讨论】:

  • 我需要 JLabels,因为我需要 280x50 的矩形,它可以在输入时更改背景(出于我的程序设计的目的)。它们包含图像和文本。我不确定JList 或JTable 是否会让我继续我的设计。
  • 可能有办法做到这一点,但我还没有足够清醒去考虑它?
猜你喜欢
  • 2013-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多