带有 GridLayout 面板的 JScrollPane

JScrollPane with GridLayout Panel

提问人:hinrich. 提问时间:11/14/2023 最后编辑:camickrhinrich. 更新时间:11/18/2023 访问量:50

问:

我有一个带有JScrollPane的JFrame()。JScrollPane 包含我的 ContainerJComponent ()。此 ContainerJComponent 包含 JComponentItems ()。这是我项目中的一个抽象问题,目的是为了理解。frameDebugPanelDebugItem

框架 我创建了一个 JFrame。For 循环用于为面板创建示例项。

public class DebugGUI {
    
    private static JFrame frame;
    private static DebugPanel panel = new DebugPanel();
    
    public static void generateGUI() {
        
        
        frame = new JFrame();
        
        
        for (int i = 1; i < 20; i++) {
            panel.addItem(0.2);
        }
        
        frame.setContentPane(new JScrollPane(panel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 
                JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS));
        frame.setVisible(true);
    }

}

面板 为简单起见,此示例中的面板占据了整个 JFrame 区域。该面板充当容器,而容器又包含项目 - 在本例中,通过 For 循环添加的 20 个项目。

public class DebugPanel extends JComponent {
    
    private static final long serialVersionUID = -7384855597611519487L;
    private LinkedList<DebugItem> items = new LinkedList<>();
    
    public DebugPanel() {
        GridLayout layout = new GridLayout();
        layout.setRows(1);
        this.setLayout(layout);
    }
    
    public void addItem(double widthRatio) {
        DebugItem item = new DebugItem(widthRatio);
        items.add(item);
        add(item);
    }


    @Override
    protected void paintComponent(Graphics g) {
        this.setPreferredSize(new Dimension((int) getPreferredSize().getWidth(), getParent().getHeight()));
        super.paintComponent(g);
        for (DebugItem item : items) {
            item.resize((int) getPreferredSize().getHeight());
        }
        
    }
}

项目 这些项目应该在面板中绘制一些东西。在我的示例中,这是一个矩形。此矩形应填充面板的整个高度,并相对于高度保持一定的宽度。

public class DebugItem extends JComponent {

    private static final long serialVersionUID = 1630268284249666775L;
    private double widthRatio;
    private int width;
    
    DebugItem(double widthRatio) {
        this.widthRatio = widthRatio;
    }
    
    void resize(int height) {
        width = (int) (height * widthRatio);
    }
    
    @Override
    protected void paintComponent(Graphics g) {
        // TODO Auto-generated method stub
        super.paintComponent(g);
        g.setColor(Color.RED);
        g.drawRect(0, 0, width, getParent().getHeight());
        
    }
}

但是,要绘制的比率不被考虑在内。JScrollPane 是无用的,因为所有项目总是填满面板。有谁知道提示?这些类是独立工作的。除了对包的引用和导入之外,代码是完整的。只需在 main 方法中调用 generateGUI() 即可。

java swing jscrollpane

评论

2赞 matt 11/14/2023
不应在 paint 组件方法中使用“setPreferredSize”。到那时有点晚了。目前尚不清楚您为什么要设置首选尺寸?DebugItem 应覆盖“getPreferredSize”,以便父组件在执行布局时知道它应该有多大。
0赞 camickr 11/15/2023
一个最小的可重现示例应该是带有 main() 方法和 import 语句的单个文件,以便我们可以轻松地复制/粘贴/编译/测试。

答:

0赞 camickr 11/15/2023 #1

在我看来,您想要一个完全填充 JScrollPane 高度的面板,并且添加到该面板的组件的宽度与高度相关。因此,您将永远不会有垂直滚动条。

如果是这样,那么我认为您可以使用可滚动面板。这将允许面板填充滚动窗格的高度。宽度将根据添加的组件数量和宽度比来确定。将根据需要出现一个水平滚动条。

基本示例:

import java.awt.*;
import java.util.*;
import javax.swing.*;

public class DebugGUI {

    public static void main(String[] args)
    {
        JFrame frame = new JFrame();

        ScrollablePanel panel = new ScrollablePanel( new GridLayout(1, 0) );
        panel.setScrollableHeight( ScrollablePanel.ScrollableSizeHint.FIT );

        for (int i = 0; i < 5; i++) {
            panel.add( new DebugItem(0.2) );
        }

        frame.setContentPane(new JScrollPane(panel, JScrollPane.VERTICAL_SCROLLBAR_NEVER,
                JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS));
        frame.setSize(400, 400);
        frame.setVisible(true);
    }

    static class DebugItem extends JComponent {

        private double widthRatio;

        DebugItem(double widthRatio) {
            this.widthRatio = widthRatio;
        }

        public Dimension getPreferredSize()
        {
            Dimension parent = super.getSize();

            return new Dimension((int)(parent.height * widthRatio), parent.height);
        }

        @Override
        protected void paintComponent(Graphics g) {
            // TODO Auto-generated method stub
            super.paintComponent(g);
            g.setColor(Color.RED);
            g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
        }
    }

}