【问题标题】:Java Swing - Scrollable PanelJava Swing - 可滚动面板
【发布时间】:2017-05-05 23:58:33
【问题描述】:

我正在尝试使用 swing 创建一个可滚动的面板。但由于我是新手,所以我没有这样做。在我的代码中,jScrollablePane 内没有显示任何内容。

我创建了一个 jframe 并在其中放置了一个 jScrollablePane。我创建了一个名为 UIElement 的类,它扩展了 jPanel,其中包括一个组件部分和子部分。子部分由其他 UIElement 组成。

  • 所有的 UIElements 都应该放在前一个 UIElement 之下。就像一个垂直列表。
  • childs 应该放在 components 下。
  • 子部分无法滚动,其高度固定为子 UIElement 的总高度。
  • 组件的固定高度为 40。而宽度可以随着其容器而扩展。
  • spacer 的宽度应固定为 40。
  • 除了spacer,所有的宽度都是动态的。
  • UIElement 可以有零个或多个子级。

这是一些图片示例,不要忘记:宽度是动态的。

这里是代码:

public static void scrollable(String title) {
    //Create and set up the window.
    JFrame frame = new JFrame(title);
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    frame.setSize(500,GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds().height);

    JPanel mainPanel = new JPanel();
    mainPanel.setLayout(new BoxLayout(mainPanel,BoxLayout.Y_AXIS));
    mainPanel.setBackground(Color.WHITE);

    mainPanel.add(new UIElement());

    JScrollPane scrollPane = new JScrollPane(mainPanel,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
    frame.getContentPane().add(scrollPane);

    //Display the window.
    frame.setVisible(true);
}

这是 UIElement 类:

public abstract class UIElement extends JPanel {
    public static final int DESIREDHEIGHT = 40;

    JPanel componentsPanel, childPanel;

    public UIElement () {
        super();
        this.setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
        this.setBackground(Color.BLACK);

        // componentsPanel
        componentsPanel = new JPanel() {
            @Override
            public Dimension getPreferredSize() {
                Dimension d = super.getPreferredSize();
                d.setSize(d.getWidth(),DESIREDHEIGHT);
                return d;
            }

            @Override
            public Dimension getMaximumSize() {
                Dimension d = super.getMaximumSize();
                d.setSize(d.getWidth(),DESIREDHEIGHT);
                return d;
            }

            @Override
            public Dimension getMinimumSize() {
                Dimension d = super.getPreferredSize();
                d.setSize(d.getWidth(),DESIREDHEIGHT);
                return d;
            }
        };
        componentsPanel.setLayout(new BoxLayout(componentsPanel,BoxLayout.X_AXIS));
        componentsPanel.setBackground(Color.BLUE);
        this.add(componentsPanel);

        // child panel
        childPanel = new JPanel() {
            @Override
            public Dimension getPreferredSize() {
                float height = 0;
                for (Component c: super.getComponents())
                    height += c.getPreferredSize().height;
                Dimension d = super.getPreferredSize();
                d.setSize(d.getWidth(),height);
                return d;
            }

            @Override
            public Dimension getMaximumSize() {
                float height = 0;
                for (Component c: super.getComponents())
                    height += c.getMaximumSize().height;
                Dimension d = super.getMaximumSize();
                d.setSize(d.getWidth(),height);
                return d;
            }

            @Override
            public Dimension getMinimumSize() {
                float height = 0;
                for (Component c: super.getComponents())
                    height += c.getMinimumSize().height;
                Dimension d = super.getMinimumSize();
                d.setSize(d.getWidth(),height);
                return d;
            }
        };
        childPanel.setLayout(new BoxLayout(childPanel,BoxLayout.Y_AXIS));
        childPanel.setBackground(Color.RED);

        // parent for childPanel and spacer
        JPanel childParent = new JPanel();
        childParent.setLayout(new BoxLayout(childParent,BoxLayout.X_AXIS));

        // spacer
        JPanel spacer = new JPanel() {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(DESIREDHEIGHT,DESIREDHEIGHT);
            }

            @Override
            public Dimension getMaximumSize() {
                return new Dimension(DESIREDHEIGHT,DESIREDHEIGHT);
            }

            @Override
            public Dimension getMinimumSize() {
                return new Dimension(DESIREDHEIGHT,DESIREDHEIGHT);
            }
        };
        spacer.setBackground(Color.RED);
        childParent.add(spacer);
        // add the childPanel later
        childParent.add(childPanel);
    }


    @Override
    public Dimension getPreferredSize() {
        Dimension c = componentsPanel.getPreferredSize();
        Dimension d = childPanel.getPreferredSize();
        return new Dimension(c.width, c.height + d.height);
    }

    @Override
    public Dimension getMaximumSize() {
        Dimension c = componentsPanel.getMaximumSize();
        Dimension d = childPanel.getMaximumSize();
        return new Dimension(c.width, c.height + d.height);
    }

    @Override
    public Dimension getMinimumSize() {
        Dimension c = componentsPanel.getMinimumSize();
        Dimension d = childPanel.getMinimumSize();
        return new Dimension(c.width, c.height + d.height);
    }

}

【问题讨论】:

    标签: java swing jframe jpanel jscrollpane


    【解决方案1】:

    不要覆盖面板的getPreferredSize()(或最大/最小尺寸)。

    每个面板将根据面板的布局管理器和添加到面板的组件来确定其首选尺寸。

    也就是说,如果面板使用布局管理器,则无需覆盖这些方法。您只需为没有布局管理器的自定义组件覆盖 getPreferredSize() 方法。在 Swing 术语中,这将是 JButton、JTextField、JLabel 等。

    因此,如果您正在创建自定义组件,那么您可以设置大小。如果您只是将一个组件用作容器,并带有一个布局管理器来容纳其他组件,那么您不需要计算大小。

    【讨论】:

    • 删除了 getPreferredSize() 方法的所有覆盖,没有工作
    • @ossobuko,您错过了我关于需要定义适当大小的“自定义组件”的观点。如果您使用的只是 JPanel,那么是的,层次结构底部的自定义面板需要适当的大小。层次结构中间的面板在我看来使用 BoxLayout,不应该覆盖大小计算。
    • 问题是所有面板都是空的。无论如何,您对 onPreferredSize() 的看法是正确的,但这不是问题。
    • @ossobuko,这是一个“问题”,如果不修复会导致结果不一致。不要忘记通过单击复选标记“接受”答案,以便人们知道问题已解决。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-26
    • 2012-06-03
    • 1970-01-01
    • 2013-11-25
    • 2012-12-01
    • 2016-04-29
    相关资源
    最近更新 更多