プレビューが画面からはみ出します

下部の[印刷][中止]ボタンが押せません

古いノートPC(WindowsXP)を借りて試したところ、下のタスクバーに[印刷][中止]ボタンが隠れてしまいました。画面が小さい場合は適当に勘案してくれると思っていました。特に、setPreferredSize()で指定しているわけですしね。ところが、入りきらないことを察知して調整はしているようなんですが、システム自身が使っている部分を考慮していないのでしょう、タスクバーがなければ大丈夫という大きさです。

タスクバーに[印刷][中止]ボタンが隠れる

マウスでサイズ変更をすることで拡大も縮小もできますが、下部が隠れると、次に進むためのボタンが押せないので困ります。上辺を下にドラッグして小さくしてからタイトルバーを持ち上げて...とするのは面倒です。

この古いノートPCは1024✕768です。今時のノートならもう少し大きいだろうと思っていたのですが、調べてみると1366×768のノートPCも多いことがわかりました。

対策の基本方針

ここで作っているプレビューは595×841ピクセルです。そもそもA4を印刷するところからスタートした解像度です。これをそのまま表示しても詳細を確認するには小さいので、画面表示の解像度を落とすのは適切ではないでしょう。

幸い不完全ながらも調整はされています。OSとアプリケーションとどちらの責任かはわかりませんがその調整方法に改善の余地があるというところで、将来的には解決されるのかもしれません。

595×841ピクセルは本体の大きさで、ダイアログにするといろいろ付いて621×971になります。WindowsXPでは625✕963になります。ウィンドウの枠の部分はOSにより違いが出ます。どんな環境でも困らない対策をする必要があります。

JOptionPaneは下部にボタンが出るので問題が深刻になりますが、たとえオリジナルのJDialogを作って下を空けたとしても右下隅にマウスを当てられなければウインドウのサイズ変更には不便なことに変わりはありません。あくまで初期状態では全体が入りきる必要があります。

ToolKit

java.awt.Toolkit; あたりを調べて、使えそそうなものを探します。getScreenSize()は主ディスプレイのスクリーンサイズが得られます。getScreenInsets(GraphicsConfiguration gc)が求めるものにより近い感じですが、GraphicsConfigurationの理解が必要です。複数の画面を使っている場合とかデバイスの本来の解像度と異なるモードで動作している場合とかなかなか面倒そうなので、getScreenSize()にしておきます。

createDialog()で作成したJDialogの高さとscreenSize.heightを比べて、はみ出す場合は縦も横もスクリーンサイズの2/3にするという設定です。

JDialog dialog = pane.createDialog("印刷プレビュー" );
int dh = dialog.getPreferredSize().height;
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int scrw = screenSize.width;
int scrh = screenSize.height;
if (dh>scrh) {
    dialog.setPreferredSize(new Dimension(scrw*2/3,scrh*2/3));
}
dialog.pack();
dialog.setResizable(true);
dialog.setVisible(true);

これはこれでうまく行きますが、2/3が小さすぎるかと9/10程度までにすると今度は右がはみ出します。出現の位置を決めた後に大きさが変更されたというところでしょうか。

Toolkit.getScreenSize()を使った調査

PreferrされているSizeはgetPreferredSize()ですが、実際のサイズにgetSize()も使えます。

TsuuchiHR.javaのcreateAndShowGUI()に追加

JDialog dialog = pane.createDialog("印刷プレビュー" );
//ajust to screen size
int dh = dialog.getPreferredSize().height;
int dw = dialog.getPreferredSize().width;
System.out.println("pref...size:"+dw+"/"+dh);//test
System.out.println("dialog size:"+dialog.getSize().width+"/"+dialog.getSize().height);//test
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int scrw = screenSize.width;
int scrh = screenSize.height;
System.out.println("screen size:"+scrw+"/"+scrh);//test
if (dh>scrh) {
    dialog.setPreferredSize(new Dimension(dw,scrh-40));
}
dh = dialog.getPreferredSize().height;
dw = dialog.getPreferredSize().width;
System.out.println("pref...size:"+dw+"/"+dh);//test
System.out.println("dialog size:"+dialog.getSize().width+"/"+dialog.getSize().height);//test
dialog.pack();
dh = dialog.getPreferredSize().height;
dw = dialog.getPreferredSize().width;
System.out.println("pref...size:"+dw+"/"+dh);//test
System.out.println("dialog size:"+dialog.getSize().width+"/"+dialog.getSize().height);//test
//ajust to screen size
dialog.setResizable(true);
dialog.setVisible(true);

実行結果(と解説)

[Y:\basicaka\akajava\javadabiyone]java print01.TsuuchiHR
pref...size:625/963
dialog size:625/780  (...これが実際に下部が見えなくなっているサイズだろう)
screen size:1024/768
pref...size:625/728  (...これがscrh-40をsetPreferredした直後のgetPrefferred())
dialog size:625/780  (...実際にはまだそうなっていないが)
pref...size:625/728  (...pack()した後はgetPreffered()はそのまま)
dialog size:625/728  (...もちろん実際の値もその値に。)

同じ状況で、paintComponent()にもTsuuchiHR(extendsJPanel)のsetPreferredSize()した値とgetSize()の値を表示させる

setPreferredSize(prevsize);
System.out.println("Tsuuchi pref. size:"+prevsize.width+"/"+prevsize.height);//test
realsize=getSize(realsize); //test method of JPanel
System.out.println(realsize); //test

getSize()で示される実際の値の初期値は、A4の本来の値になっている(本来の画面がViewportから覗いているという理想的な状態である)。

表示後マウス操作で横を広げたものだが、実際の値はいったん下がってから上がってくる。理由は不明。

Tsuuchi pref. size:579/819   ...(setPreferredSize()した値)
java.awt.Dimension[width=596,height=842] ...(getSize()の値)
Tsuuchi pref. size:579/819
java.awt.Dimension[width=579,height=819]
Tsuuchi pref. size:580/821
java.awt.Dimension[width=580,height=819]
Tsuuchi pref. size:594/841
java.awt.Dimension[width=594,height=821]
Tsuuchi pref. size:597/845
java.awt.Dimension[width=597,height=841]
Tsuuchi pref. size:604/855
java.awt.Dimension[width=604,height=845]
Tsuuchi pref. size:607/859
java.awt.Dimension[width=607,height=855]
Tsuuchi pref. size:608/860
java.awt.Dimension[width=608,height=859]
Tsuuchi pref. size:608/860
java.awt.Dimension[width=608,height=860]

スクリーンサイズに余裕のあるDebian/linuxの場合

adachi@debian64:/media/S1T/basicaka/akajava/javadabiyone$ java print01.TsuuchiHR 
pref...size:621/971
dialog size:629/968
screen size:3200/1200
pref...size:621/971
dialog size:629/968
pref...size:621/971
dialog size:621/971

Tsuuchi pref. size:596/842
java.awt.Dimension[width=596,height=842]
Tsuuchi pref. size:596/842
java.awt.Dimension[width=598,height=842]
Tsuuchi pref. size:623/882
java.awt.Dimension[width=638,height=842]
Tsuuchi pref. size:623/882
java.awt.Dimension[width=623,height=882]
Tsuuchi pref. size:679/961
java.awt.Dimension[width=679,height=882]

運用形

TsuuchiHR.java

JDialog dialog = pane.createDialog("印刷プレビュー" );
//ajust to screen size
int dh = dialog.getPreferredSize().height;
int dw = dialog.getPreferredSize().width;
//Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
//int scrh = screenSize.height;
int scrh = Toolkit.getDefaultToolkit().getScreenSize().height;
if (dh>scrh) {
    dialog.setPreferredSize(new Dimension(dw,scrh-40));
}
dialog.pack();
//ajust to screen size
dialog.setResizable(true);
dialog.setVisible(true);

GraphicsEnvironmentにまつわるメソッド(以下参考資料)

java.awt.GraphicsEnvironment

static GraphicsEnvironment 	getLocalGraphicsEnvironment()
ローカルの GraphicsEnvironment を返します。

java.awt.GraphicsEnvironment
abstract GraphicsDevice 	getDefaultScreenDevice()
デフォルト画面 GraphicsDevice を返します。

java.awt.GraphicsDevice

abstract GraphicsConfiguration 	getDefaultConfiguration()
この GraphicsDevice に関連付けられたデフォルトの GraphicsConfiguration を返します。

java.awt.GraphicsConfiguration

abstract Rectangle 	getBounds()
デバイス座標内の GraphicsConfiguration の境界を返します。

java.awt.Toolkit

public Insets getScreenInsets(GraphicsConfiguration gc)
スクリーンのインセットを返します。

GraphicsEnvironmentを使用した調査

java.awt.GraphicsEnvironment genv = java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment();
java.awt.GraphicsDevice  gdev        = genv.getDefaultScreenDevice();
java.awt.GraphicsConfiguration gconf = gdev.getDefaultConfiguration();
java.awt.Rectangle rect = gconf.getBounds();
System.out.println("---env--------");
System.out.println("bounds:"+rect.getWidth()+"*"+rect.getHeight());

java.awt.Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gconf);
System.out.println("insets:"+insets.toString());

WindowsXPで高さの足りないPCでの結果

getBounds()は相変わらず全体の大きさだが、InsetsのbottomでWindowsのタスクバーの高さがわかる

[Y:\basicaka\akajava\javadabiyone]java print01/TsuuchiHR
---env--------
bounds:1024.0*768.0
insets:java.awt.Insets[top=0,left=0,bottom=30,right=0]

GNOME 3.4.2 高さの十分なPCでの結果

GNOMEにも上部に常時表示されるバーがあるが、これをはかることができない。

adachi@debian64:/media/S1T/basicaka/akajava/javadabiyone$ java print01.TsuuchiHR 
---env--------
bounds:1920.0*1200.0
insets:java.awt.Insets[top=0,left=0,bottom=0,right=0]

完全に把握できるわけではないので、Toolkit.getScreenSize()をつかうに留めておく。

ウィンドウの左上隅にウィンドウのコントロールを置いたMacの設計は合理的であったと改めて思う。