java - AWT 滚动 Pane 滚动条在调整大小时闪烁

标签 java swing canvas jframe awt

我在 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 对等点的实现中的错误引起的。 ( Source Here ) 我复制了我认为有错误的方法(链接中的第 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 都应该在我上面展示的简单情况下正常工作。

最佳答案

对于 future 的读者来说,如果没有 SSCCE,很难为您提供帮助

However, in practice both scrollbars seem to flicker while the resize operation is occurring and may even persist until the next redraw after the operation completes

  • 使用过的 LCD/LED 面板导致这些闪烁(包括 MsExcell,例如,顺便说一句,多次讨论过),

  • 带有 JScrollPane 的 Swing JFrame 也会出现同样的闪烁

  • 未在 CRT 或等 ionic 显示器上呈现

  • 如果您在 PC 上播放全高清视频,那么每个好的多媒体播放器都会等到调整大小结束,然后将可用空间填充到其容器中

<小时/>
  • 你必须添加 ComponentListener,将 Swing Timer 放在那里,延迟很小(KMPlayer 显示 350-500 毫秒),直到调整大小,继续调用 Timer#restart,

  • Canvas 是 CAD/CAM、OpenGL(CL) 的良好解决方法,良好的 Java 视频播放器基于 AWT

  • 你必须避免将 Swing Container 与 AWT 内容混合,让一切都基于 AWT(未装饰容器)

关于java - AWT 滚动 Pane 滚动条在调整大小时闪烁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11212606/

相关文章:

java - 应用程序如何知道它正在 Google AppEngine 上运行?

java - 如何将卡片布局格式添加到我的主游戏屏幕,以便当我单击按钮时它从主菜单屏幕更改为我提供的游戏屏幕代码

java - 如何让按钮setText hibernate ?

javascript - 如何使用 javascript 或 jquery 更改 Canvas 元素的 fillStyle?

JavaScript 对象 : 'addEventListener is not a function'

java - 非常大的数字的 Diffie-Hellman 计算

java - 提交有效表单后在 Liferay 中重定向?

javascript - 中心 bezierCurve html5 Canvas 绘图?

java - 我可以将 Swing 外观应用到 AWT 小部件吗?

java - 浏览要读取的文本文件