2013-06-03 3 views
1

Я размещаю изображения в сетке с помощью MigLayout. Я мог бы получить ширину, чтобы взять все пространство, доступное в столбце, но затем я хочу, чтобы высота увеличивалась соответственно, так что пропорция изображения все еще фиксировалась.MigLayout: как изменить размер пропорционально ширине (сохраняя соотношение сторон)?

Каков наилучший подход для этого? Могу ли я сделать это с выражением в ограничении, или мне нужно переопределить getPreferredSize()?

Спасибо!

ответ

1

После многих исследований я понимаю, что с Swing нет хорошего способа сделать это. Проблема связана не только с MigLayout, но и с макетами типа ScrollPaneLayout, которая предполагает, что предпочтительная высота останется неизменной после другой эффективной ширины (которая не является предпочтительной шириной).

Есть два варианта:

1) В настоящее время я делаю свою собственную реализацию MigLayout с компонентом ограничением соотношения сторон. Вы можете скачать его здесь:

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

До сих пор, она работает с сокращением и растет X в простом случае сетки с 1 компонентной/сотой. Я все еще должен тестировать с охватом, течением в ячейке и стыковкой ..... Я буду держать этот репозиторий обновленным, и любая помощь приветствуется.

Как вы, вероятно, используете его как представление на ViewPort, вам придется немного взломать getPreferredSize представления, если вы используете его с Scrollable.getScrollableTracksViewportWidth(), возвращающим true, поэтому он не возвращает реальную предпочтительную высоту, но ту, которая соответствует ширине. В моем коде есть геттер для сетки, а сетка имеет функцию возврата предпочтительной высоты для заданной ширины.

2) Сохраняя текущую реализацию MigLayout нетронутой (4.2 на момент ответа), я нашел только один способ добиться этого: добавив обратный вызов макета и внедряя метод getSize() с чем-то вроде этого:

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), чтобы установить вручную предпочтительный размер макета, так как после обратный вызов становится предвзятым.

+0

Кстати, последний код может быть 'add (tmpImage, new CC(). ShrinkX (100) .minWidth (" 1 "). MinHeight (" 1 "))' если вы предпочитаете. – wchargin

+0

ok, старый код с функцией «getSize()» имел недостаток. Он считает, что ширина не изменится в течение этого цикла макета. Итак, мне пришлось реализовать «currentBounds (ComponentWrapper)», который выполняется в самом конце цикла компоновки, и он проверяет, что аспектный ранг по-прежнему прав. Это могло быть проще и чище, если MigLayout проходил в правильном обратном вызове эффективные размеры «horSizes» и «verSizes» с возвратом «doAgain». Ответ отредактирован, чтобы показать, как у меня это сейчас .... – lqbweb

+0

ОК, я не отредактировал свой ответ, наконец, потому что есть еще одна проблема. Боюсь, для этого нет чистого решения. Когда я верну свой BoundSize в getSize, он будет использоваться позже, чтобы неправильно рассчитать предпочтительный размер Grid. Я попытаюсь реализовать это на моей собственной реализации MigLayout, так как официальная поддержка, которую я понимаю, довольно бедна. – lqbweb

Смежные вопросы