MigLayoutでグリッド状に画像を配置しています。列で使用可能なスペース全体を使用する幅を取得できますが、それに応じて高さを大きくして、画像の比率を固定したままにします。
これに最適なアプローチは何ですか?制約の式でそれを行うことができますか、または getPreferredSize() をオーバーライドする必要がありますか?
ありがとう!
MigLayoutでグリッド状に画像を配置しています。列で使用可能なスペース全体を使用する幅を取得できますが、それに応じて高さを大きくして、画像の比率を固定したままにします。
これに最適なアプローチは何ですか?制約の式でそれを行うことができますか、または getPreferredSize() をオーバーライドする必要がありますか?
ありがとう!
いろいろ調べた結果、Swing でこれを行う良い方法はないことに気付きました。この問題は、MigLayout だけでなく、ScrollPaneLayout などのレイアウトからも発生します。これは、異なる有効幅 (優先幅ではない) の後、優先高が同じままであることを前提としています。
次の 2 つのオプションがあります。
1) 現在、アスペクト比コンポーネントの制約を使用して MigLayout を独自に実装しています。ここからダウンロードできます。
https://github.com/lqbweb/miglayout-aspect
これまでのところ、1 コンポーネント/セルの単純なグリッド ケースで、X の縮小と拡大で動作します。スパニング、セル内のフロー、およびドッキングをまだテストする必要があります.....そのリポジトリを最新の状態に保ちます。どんな助けも大歓迎です。
おそらくViewPortのビューとして使用するため、trueを返すScrollable.getScrollableTracksViewportWidth()で使用する場合は、ビューのgetPreferredSizeを少しハックする必要があるため、実際の優先高は返されませんが、幅に合わせたもの。私のコードには、グリッドのゲッターがあり、グリッドには、指定された幅の優先高を返す関数があります。
2) MigLayout の現在の実装 (この回答の時点では 4.2) を変更せずに、これを実現する方法を 1 つだけ見つけました。レイアウトにコールバックを追加し、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) を追加して更新し続ける必要があります。これは、コールバック後にバイアスがかかるためです。