我遇到了 java.awt.ScrollPane 类的 SCROLLBARS_AS_NEEDED 显示策略处理组件调整大小的问题。理想情况下,如果我有一个包含明显小于 Scrollpane 的 Component 的 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.getPreferredSize() 而不是 c.size()。如果 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 是不可协商的。在我的实际应用程序中,我使用 Java AWT Native Interface 非常快速地绘制了一些东西。
-虽然我阅读了有关 Java 7 和 Java 6 更高版本中轻/重兼容性的新改进的文档,但我并没有真正看到任何一种情况的改进,所以我决定坚持使用 awt.ScrollPane 而不是 swing.JScrollPane。无论哪种方式,ScrollPane 都应该在我上面展示的简单案例中正常工作。