MigLayout:如何根据宽度按比例调整高度(保持纵横比)?

时间:2013-06-03 17:17:52

标签: java swing layout aspect-ratio miglayout

我正在使用MigLayout在网格中排列图像。我可以获得宽度来获取列中可用的整个空间,但之后我希望高度相应增长,以便图像的比例仍然固定。

最佳方法是什么?我可以使用约束中的表达式来执行此操作,还是必须覆盖getPreferredSize()?

谢谢!

1 个答案:

答案 0 :(得分:1)

经过大量的研究,我意识到使用Swing没有很好的方法。问题不仅来自MigLayout,还来自ScrollPaneLayout等布局,它假设在不同的有效宽度(不是首选宽度)之后,首选高度将保持不变。

有两种选择:

1)目前,我正在使用宽高比组件约束来实现我自己的MigLayout实现。你可以从这里下载:

https://github.com/lqbweb/miglayout-aspect

到目前为止,它适用于在具有1个组件/单元的简单网格情况下缩小和增长X.我仍然需要测试跨越,流动的细胞和对接.....我会保持更新的存储库,欢迎任何帮助。

由于您可能将其用作ViewPort上的视图,如果您在Scrollable.getScrollableTracksViewportWidth()返回true的情况下使用它,则必须破解视图的getPreferredSize,因此它不会返回真实首选高度,但与宽度匹配的高度。在我的代码中,网格有一个getter,网格有一个返回给定宽度的首选高度的函数。

2)保持MigLayout的当前实现不变(在本回答时为4.2),我只找到了一种方法来实现这一点:通过向布局添加回调并使用以下内容实现getSize()方法: / p>

    migLayout.addLayoutCallback(new LayoutCallback() {

        /**
         * This is run before the layout starts laying out
         */
        @Override
        public BoundSize[] getSize(ComponentWrapper comp) {
            if(comp.getComponent() instanceof DCMImageWrapper) {
                DCMImageWrapper img=(DCMImageWrapper) comp.getComponent();    //this is the BufferedImage embedded in a JLabel
                int calculatedHeight=img.getHeightFor(comp.getWidth());
                UnitValue maxHeight=new UnitValue(calculatedHeight);
                BoundSize height=new BoundSize(maxHeight, maxHeight, maxHeight, null);

                return new BoundSize[]{null, height};
            } else {
                return null;
            }
        }

        private double getCurrentAspect(ComponentWrapper comp) {
            if(comp.getWidth()==0 || comp.getHeight()==0) return 0;
            double currentAspect=comp.getWidth()/(double)comp.getHeight();
            return currentAspect;
        }

        /**
         * Check if the aspect still valid
         */
        @Override
        public void correctBounds(ComponentWrapper comp) {
            if(comp.getComponent() instanceof DCMImageWrapper) {
                DCMImageWrapper img=(DCMImageWrapper) comp.getComponent();

                double currentAspect=getCurrentAspect(comp);
                double origAspect=img.getDCMImage().getAspect();
                double currentError=Math.abs(origAspect-currentAspect);
                if(currentError > img.getDCMImage().getAspectError()) {
                    //recalculate layout
                    revalidate();
                }
            }
        }

    });

然后,添加如下组件:

CC constraints=new CC();
constraints.shrinkX(100);
constraints.minWidth("1");
constraints.minHeight("1");
add(tmpImg, constraints);

但是,您必须添加并保持更新布局约束(LC)以手动设置布局的首选大小,因为在回调后它会产生偏差。