java.awt.ScrollPaneクラスのSCROLLBARS_AS_NEEDED表示ポリシー処理コンポーネントのサイズ変更に問題があります。理想的には、Scrollpaneよりも大幅に小さいコンポーネントを含むScrollPaneがあり、Scrollpaneを子コンポーネントよりもまだ大きいサイズに縮小すると、スクロールバーは表示されません。ただし、実際には、サイズ変更操作の実行中に両方のスクロールバーがちらつくように見え、操作が完了した後の次の再描画まで持続する場合もあります。これが私が何を意味するかを示すための小さな例です:
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.ScrollPane;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Tester implements Runnable{
/**
* @param args
*/
public static void main(String[] args) {
System.setProperty("sun.awt.noerasebackground", "true");
Tester t = new Tester();
SwingUtilities.invokeLater(t);
}
@SuppressWarnings("serial")
@Override
public void run() {
JFrame frame = new JFrame("Tooltip tester");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 800);
Canvas c = new Canvas(){
@Override
public void paint(Graphics g){
g.setColor(Color.WHITE);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
}
};
c.setPreferredSize(new Dimension(400, 400));
ScrollPane s = new ScrollPane();
s.add(c);
frame.add(s);
frame.setVisible(true);
}
}
上記のアプリケーションでウィンドウを縮小すると、スクロールバーが点滅します。これは、ScrollPaneのピアの実装のバグが原因であると思います。(ソースはこちら)エラーがあると思われるメソッドをコピーしました(リンクの145行目)。
Dimension getChildSize() {
ScrollPane sp = (ScrollPane)target;
if (sp.countComponents() > 0) {
Component c = sp.getComponent(0);
return c.size();
} else {
return new Dimension(0, 0);
}
}
私には、getChildSize()メソッドはc.size()ではなくc.getPreferredSize()を呼び出す必要があるようです。ScrollPaneの子のサイズが現在の推奨サイズよりも大きい場合は、スクロールバーが表示されずに縮小できるはずです(私の意見では)。この理論をテストするために、上記の例のsize()メソッドをオーバーライドします。
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.ScrollPane;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Tester implements Runnable{
/**
* @param args
*/
public static void main(String[] args) {
System.setProperty("sun.awt.noerasebackground", "true");
Tester t = new Tester();
SwingUtilities.invokeLater(t);
}
@SuppressWarnings("serial")
@Override
public void run() {
JFrame frame = new JFrame("Tooltip tester");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 800);
Canvas c = new Canvas(){
private Dimension prefSize = new Dimension();
@Override
public void paint(Graphics g){
g.setColor(Color.WHITE);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
}
@Override
public void setPreferredSize(Dimension preferredSize) {
prefSize = preferredSize;
super.setPreferredSize(preferredSize);
}
@Override
public Dimension size() {
return prefSize;
}
};
c.setPreferredSize(new Dimension(400, 400));
ScrollPane s = new ScrollPane();
s.add(c);
frame.add(s);
frame.setVisible(true);
}
}
このコードは、私が望むとおりに動作します。ただし、size()メソッドをオーバーライドして、ドキュメントに記載されている以外のことを行うことは、この問題を解決するための特に洗練された方法ではありません。私はここで何か間違ったことをしているに違いないように感じます。X11用のScrollPaneピアのかなり基本的な機能が壊れている可能性はありますか?
その他の関連する注意事項:
-java.awt.Canvasの使用は、私の目的では交渉できません。私の実際のアプリケーションでは、JavaAWTネイティブインターフェイスを使用して非常にすばやく何かを描画しています。
-Java7以降のバージョンのJava6でのライト/ヘビー級の互換性の新しい改善に関するドキュメントを読みましたが、どちらの場合も実際には改善が見られなかったため、swing.JScrollPaneではなくawt.ScrollPaneを使用することにしました。いずれにせよ、上記の単純なケースではScrollPaneが正しく機能するはずです。