基本的なセットアップは次のとおりです。私は固定サイズの下部コンポーネントとサイズ変更可能な上部コンポーネントを持ちたい垂直 JSplitPane を持っていますsetResizeWeight(1.0)
。このアプリケーションには、「デフォルト」のウィンドウ構成を復元するためのボタンがあります。ウィンドウのデフォルトの高さはデスクトップの高さで、デフォルトの分割位置は分割ペインの下部から 100 ピクセルです。
仕切りの位置を 100px に設定するには、JSplitPane の高さを 100 に設定します。問題は、この直前に JFrame のサイズを変更することです。コードはボタン コールバックにあるため、JSplitPane は無効化されていますが、まだサイズ変更されていません。そのため、仕切りの位置が正しく設定されていません。
これがSSCCEです。ボタンを 2 回クリックして、問題を確認します。最初のクリックでウィンドウのサイズが変更されますが、仕切りの位置は同じままです (ウィンドウの下部に対して)。ウィンドウ サイズが変更されていないため、2 回目のクリックで仕切りが適切に移動します。
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GraphicsConfiguration;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JSplitPane;
public class SSCCE {
/**
* @param args unused
*/
public static void main(String[] args) {
new SSCCE();
}
private final JFrame f = new JFrame("JSplitPane SSCE");
private final JSplitPane sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT,true);
public SSCCE() {
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
sp.add(new JLabel("top"));
sp.add(new JLabel("bottom"));
sp.setResizeWeight(1.0);
f.getContentPane().add(sp);
f.getContentPane().add(new JButton(new AbstractAction("Resize to Default") {
@Override
public void actionPerformed(ActionEvent e) {
restoreDefaults();
}
}),BorderLayout.PAGE_END);
f.setSize(400,300);
f.setVisible(true);
}
void restoreDefaults() {
f.setSize(f.getWidth(), getDesktopRect(f.getGraphicsConfiguration()).height);
sp.setDividerLocation(sp.getSize().height - 100); // Does not work on first button press
}
Rectangle getDesktopRect(GraphicsConfiguration gc) {
Toolkit toolkit = Toolkit.getDefaultToolkit();
Dimension size = toolkit.getScreenSize();
Insets insets = toolkit.getScreenInsets(gc);
return new Rectangle(insets.left, insets.top, size.width - (insets.left + insets.right), size.height - (insets.top + insets.bottom));
}
}
これを回避する方法をいくつか考えてみましたが、どれもハックのように思えます。これまでのところ、フレーム サイズの設定と分割位置の設定の間に呼び出しを行うのが最善の方法でしたがf.validate()
、早期に検証を強制すると副作用が生じるのではないかと懸念しています。
私が考えたもう 1 つのオプションEventQueue.invokeLater()
は、イベント キューの最後に仕切りの位置を設定するための呼び出しを配置するために使用することです。しかし、それは私には危険に思えます。私は、JSplitPane がその時点で検証済みであると想定しています。
より良い方法はありますか?