JScrollPane - 滚动时的视觉故障

Mik*_*rin 6 java swing jscrollpane

在滚动时,有一些关于JScrollPane中类似故障的主题:

但他们缺乏SSCCE和案件的一些解释,所以我将添加缺少的东西.

首先,这是一个在纯Swing上编写的小例子,没有使用第三方代码:

public class ScrollGlitchExample extends JFrame
{
    public ScrollGlitchExample () throws HeadlessException
    {
        super ();

        final JPanel top = new JPanel ();
        top.setPreferredSize ( new Dimension ( 300, 50 ) );
        top.setBorder ( BorderFactory.createLineBorder ( Color.BLACK ) );
        add ( top, BorderLayout.NORTH );

        final JPanel panel = new JPanel ( new GridLayout ( 500, 1 ) );
        for ( int i = 0; i < 500; i++ )
        {
            panel.add ( new JButton ( "button" + i ) );
        }
        final JScrollPane scroll = new JScrollPane ( panel );
        scroll.setPreferredSize ( new Dimension ( 300, 300 ) );
        add ( scroll, BorderLayout.CENTER );

        final JPanel bottom = new JPanel ();
        bottom.setPreferredSize ( new Dimension ( 300, 50 ) );
        bottom.setBorder ( BorderFactory.createLineBorder ( Color.BLACK ) );
        add ( bottom, BorderLayout.SOUTH );

        setDefaultCloseOperation ( WindowConstants.EXIT_ON_CLOSE );
        pack ();
        setLocationRelativeTo ( null );
    }

    public static void main ( final String[] args )
    {
        SwingUtilities.invokeLater ( new Runnable ()
        {
            @Override
            public void run ()
            {
                new ScrollGlitchExample ().setVisible ( true );
            }
        } );
    }
}
Run Code Online (Sandbox Code Playgroud)

这是一个小例子 - 顶部和底部有两个面板,并在框架中间滚动有大量内容.那么,这个特定示例中的毛刺是怎样的:

滚动故障屏幕截图

要重现它:您必须使用鼠标滚轮向下滚动JScrollPane ,通过拖动滚动条滚动不会导致此问题,可能是由于大量重绘或其他一些细微差别.滚动时,您会看到与按钮重叠的白线.在BLIT_SCROLL_MODE JScrollPane中简单地复制之前绘制的部分以最大化滚动速度并最小化使用的RAM,但它似乎有某种错误.

为了使效果更加"恐怖",您可以提高滚动速度:

scroll.getVerticalScrollBar ().setUnitIncrement ( 30 );
Run Code Online (Sandbox Code Playgroud)

滚动一段时间后你会看到类似的东西:

在此输入图像描述

当我从Windows 7切换到Windows 8时,这个故障第一次出现,所以这似乎也是一些与Windows 8相关的问题.它可以在Windows 8系统上使用任何版本的JDK(6/7/8)进行复制.我不确定这是否可以在其他系统上重现.

还有一个观察 - 类似的问题似乎出现在Windows 8上甚至与Java无关的应用程序中.例如,我在Skype聊天窗口中已经多次看到这个问题,有时在文本编辑器和其他使用滚动的应用程序中.同时,所有这些应用程序(相同版本)在其他Windows版本上都没有此问题.

所以这可能是一些常见的Windows 8问题,但我无法100%确定,因为它有一个简单的(但实际上不是很好的)代码解决方法:

scroll.getViewport ().setScrollMode ( JViewport.BACKINGSTORE_SCROLL_MODE );
scroll.getViewport ().setScrollMode ( JViewport.SIMPLE_SCROLL_MODE );
Run Code Online (Sandbox Code Playgroud)

使用其中一种滚动模式而不是JViewport.BLIT_SCROLL_MODE(在Swing中设置为默认滚动模式,因为它最有效)修复了该问题.使用JViewport.BACKINGSTORE_SCROLL_MODE而不是默认模式可能是最好的解决方法,但它仍然是一种解决方法,并且在对此滚动模式的注释中描述了一些缺点:

/**
  * Draws viewport contents into an offscreen image.
  * This was previously the default mode for <code>JTable</code>.
  * This mode may offer advantages over "blit mode"
  * in some cases, but it requires a large chunk of extra RAM.
  *
  * @see #setScrollMode
  * @since 1.3
  */
public static final int BACKINGSTORE_SCROLL_MODE = 2;
Run Code Online (Sandbox Code Playgroud)

总结一下:

  • 这个故障几乎出现在Windows 8上的任何滚动中
  • 它可以通过使用鼠标滚轮滚动来重现,但不能拖动滚动条
  • 可以通过在JScrollPane的JViewport中更改滚动模式来修复它

我的问题是:

  • 任何人都可以确认此问题出现在Windows 8以外的任何其他操作系统上吗?
  • 什么可能是这个问题的真正来源?
  • 是否有任何已知/好方法来修复此w/o修改滚动模式?

更新1

由于这个问题似乎特定于我的硬件/软件,我将尝试更新各种东西(系统,视频驱动程序,做一些清理).但是对于那些遇到同样问题的人来说,这仍然有用,所以如果我能理解究竟是什么导致了这个问题以及如何修复它,我会发布更多更新.


更新2

安装了十几个Windows更新(Windows仍然只有8个,而不是8.1个)后,这个问题就消失了.我不确定哪个更新确切地解决了这个问题,但肯定是一些系统核心更新.因此,如果您使用未安装最新更新的早期版本的Windows 8,则基本上会出现此问题.

tra*_*god 4

虽然GridLayout(0, 1)可以在一列中排列任意数量的组件,但对于超过数百个单元格,结果的扩展性很差。个人资料是确定的。相反,请使用仅呈现可见单元格的组件,例如JListJTable,如此处建议的那样