在显示滚动条之前将内容缩小到 minSize

Shrink content to minSize before showing scrollbars

我想要实现的是,JScrollPane 会在内容缩小到最小尺寸后显示滚动条。滚动条出现后,面板应该有最小尺寸。 我能实现的最接近的事情是在 jpanel 上实现 Scrollable 并覆盖 getScrollableTracksViewportHeight 和 getScrollableTracksViewportWidth 方法。

public class EditPanel extends JPanel implements Scrollable {

    @Override
    public Dimension getPreferredScrollableViewportSize() {
        return super.getPreferredSize();
    }

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

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

    @Override
    public boolean getScrollableTracksViewportWidth() {
        return this.getMinimumSize().width < this.getWidth();
    }

    @Override
    public boolean getScrollableTracksViewportHeight() {
        return this.getMinimumSize().height < this.getHeight();
    }
}

然而,当内容缩小到其最小尺寸以下时,这会导致滚动条闪烁。

如果滚动条不闪烁,我怎样才能做到这一点? 这是我用来测试这个的代码:

public class Main {
    public static void main(String[] args) {
        JFrame f = new JFrame();
        JScrollPane sp = new JScrollPane();
        EditPanel p = new EditPanel();
        p.setMinimumSize(new Dimension(200, 200));
        p.setPreferredSize(new Dimension(500, 500));
        p.setBackground(Color.white);

        sp.setViewportView(p);
        f.setContentPane(sp);

        f.pack();
        f.setVisible(true);
    }
}

您想根据视口的大小而不是面板进行比较:

@Override
public boolean getScrollableTracksViewportWidth() {
    //return this.getMinimumSize().width < this.getWidth();
    return this.getMinimumSize().width < getParent().getWidth();
}

@Override
public boolean getScrollableTracksViewportHeight() {
    //return this.getMinimumSize().height < this.getHeight();
    return this.getMinimumSize().height < getParent().getHeight();
}

编辑:

when the scrollbars show up, EditPanels size will be preferred size instead of minimum size.

滚动条基于视口中组件的首选大小。因此,您还需要动态管理首选大小。可能是这样的:

@Override
public Dimension getPreferredSize()
{
    Dimension preferredSize = super.getPreferredSize();
    Component parent = getParent();

    if (parent == null)
        return preferredSize;

    Dimension parentSize = parent.getSize();
    Dimension minimumSize = getMinimumSize();

    int width = Math.min(preferredSize.width, parentSize.width);
    width = Math.max(width, minimumSize.width);

    int height = Math.min(preferredSize.height, parentSize.height);
    height = Math.max(height, minimumSize.height);

    return new Dimension(width, height);
}