MigLayout: how to resize the height proportionally to the width (keeping the aspect ratio)?

南笙酒味 提交于 2021-01-28 18:50:20

问题


I'm arranging images in a grid with MigLayout. I could get the width to take the whole space available in the column, but then I want the height to grow accordingly so the proportion of the image still fixed.

What is the best approach for this? Could I do that with an expression in the constraint or I have to override the getPreferredSize()?

Thanks!


回答1:


After a lot of researching, I realize that there is no nice way of doing this with Swing. The problem is not only coming from MigLayout but also from layouts like ScrollPaneLayout, which assumes that the preferred height will remain the same after a different effective width (which is not the preferred width).

There are two options:

1) Currently, I'm doing my own implementation of MigLayout with an aspect ratio component constraint. You can download it from here:

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

So far, it works with shrinking and growing X in a simple grid case with 1 component / cell. I still have to test with spanning, flowing in the cell and docking..... I'll keep that repository updated and any help is well welcome.

As you will probably use it as a view on a ViewPort, you will have to hack a bit the getPreferredSize of the view if you use it with the Scrollable.getScrollableTracksViewportWidth() returning true, so it doesn't return the real preferred height but the one that matches the width. In my code there is a getter for the grid, and the grid has a function to return a preferred height for a given width.

2) Keeping the current implementation of MigLayout untouched (4.2 at the time of this answer), I only found one way to achieve this: by adding a callback to the layout and implementing getSize() method with something like this:

    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();
                }
            }
        }

    });

and then, adding the component like:

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

But, you will have to add and keep updated a layout constraint (LC) to set manually the preferred size of the layout, as after the callback it gets biased.



来源:https://stackoverflow.com/questions/16902256/miglayout-how-to-resize-the-height-proportionally-to-the-width-keeping-the-asp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!