调整大小时,AWT Scrollpane滚动条会闪烁

时间:2012-06-26 17:15:45

标签: java swing canvas jframe awt

我遇到了java.awt.ScrollPane类的SCROLLBARS_AS_NEEDED显示策略处理组件调整大小的问题。理想情况下,如果我的ScrollPane包含一个比Scrollpane小得多的Component,并且我将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()方法以执行除文档所说的应该执行的操作之外的其他操作并不是解决此问题的特别优雅的方法。我觉得我必须在这里做错事。 ScrollPane对等X11的相当基本功能是否可能被破坏?

其他一些相关说明:
- 出于我的目的,java.awt.Canvas的使用是不可协商的。在我的实际应用中,我使用Java AWT Native Interface非常快速地绘制了一些东西 - 虽然我在Java 7及更高版本的Java 6中阅读了有关轻/重量级兼容性的新改进的文档,但我在两种情况下都没有看到改进,所以我决定坚持使用awt.ScrollPane而不是swing.JScrollPane。无论哪种方式,ScrollPane都应该在上面显示的简单情况下正常工作。

1 个答案:

答案 0 :(得分:1)

没有SSCCE,未来的读者很难帮助你

  

但实际上,在调整大小操作时,两个滚动条似乎都会闪烁,甚至可能会持续到操作完成后的下一次重绘

  • 使用LCD / LED面板导致闪烁(包括MsExcell,例如btw多次讨论),

  • 与JScrollPane的Swing JFrame相同的闪烁

  • 未在CRT或等离子显示屏上显示

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


  • 你必须添加ComponentListener,把Swing Timer放到一个小延迟(KMPlayer告诉我350-500milisecs),直到调整大小继续调用Timer#restart,

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

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