Java JScrollPane-滚动时出现视觉故障

Java JScrollPane-滚动时出现视觉故障,java,swing,jscrollpane,Java,Swing,Jscrollpane,在滚动时,JScrollPane中出现了一些类似的问题,如: 但他们缺乏SSCCE和对该案例的一些解释,因此我将补充缺少的内容 首先,这里是一个在纯Swing上编写的小示例,没有使用第三方代码: public class ScrollGlitchExample extends JFrame { public ScrollGlitchExample () throws HeadlessException { super (); final

在滚动时,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 );
            }
        } );
    }
}
滚动一段时间后,您将看到类似的内容:

这个小故障第一次出现在我从Windows7切换到Windows8时,所以这似乎也是Windows8相关的问题。它可以在Windows8系统上使用任何版本的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 );
使用其中一种滚动模式而不是JViewport.BLIT_scroll_模式(在Swing中设置为默认滚动模式,因为它是最有效的)修复了该问题。同时,使用JViewport.BACKINGSTORE_SCROLL_模式而不是默认模式可能是最佳的解决方法,但它仍然是一种解决方法,并且在对此滚动模式的评论中也有一些缺点:

/**
  * 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;
总结:

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

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

更新1

由于这个问题似乎是针对我的硬件/软件的,我将尝试更新各种内容(系统、视频驱动程序、做一些清理)。但这对那些遇到同样问题的人来说可能还是有用的,所以如果我能理解到底是什么导致了这个问题,以及如何解决这个问题,我会发布更多的更新


更新2


在安装了十几个Windows更新(Windows仍然是8,而不是8.1)之后,这个问题就消失了。我不确定哪一次更新确实解决了这个问题,但肯定是一些系统核心更新。因此,如果您使用的是早期版本的Windows 8,而没有安装最新的更新,则基本上可能会发生此问题。

虽然
GridLayout(0,1)
可以在一列中排列任意数量的组件,但对于几百个以上的单元格,结果的伸缩性很差。当然相反,使用只渲染可见单元格的组件,如建议的
JList
JTable

1。Win8、ent 64b、物理GPU(HP low_profile)、稳定的JDK 17_021、有趣的JRE 17_051、2中没有问题。注意:ScrollMode仅针对父对象为JViewPort的对象而设计,而不是(没有)JScrollPaneis可以通过使用Thread.sleep和JScrollBar的随机位置进行模拟,但在Java6(可能是Java5)中导致它在我的Win7中运行良好,但是,由于您的代码正在违反Swing的单线程规则,因此您的代码有权拥有JVM感觉到的任何奇怪的bug。在主菜单中添加
invokeLater
。请看,您可以找到这方面的详细解释。@Mikle Garin通过在很短的时间内阻止EDT,通过使用JScrollbars max value中的Thread.sleep(20)和Randon,可以看到类似的情况,:-)重新启动Eclipse,更新GPU的驱动程序,最后,你在主板GPU上运气不好-这个滚动故障的问题实际上是在未更新的操作系统上。虽然这是我第一次看到更新会在Java应用程序中导致如此奇怪的绘图行为,假设它自己处理框架内的所有绘图。我使用了一个带有网格布局和大量按钮的面板,只是为了在其中有垂直滚动和一些自重绘元素(您可以在出现故障后翻转按钮,并将其重新喷漆).按钮本身和面板可以替换为任何描述的错误。这样看更容易。是的,JList或JTable故障仍然存在。正如我前面所说的-此错误与滚动内容无关,但与一些绘图或甚至本地内容相关。如果您看到此
JTable的类似效果
,问题可能特定于您的操作系统/平台/版本。是的,我对这些示例也有问题,请查看此屏幕截图:
/**
  * 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;