如何在JScrollPane上禁用滚轮滚动事件的默认绘制行为 [英] How to disable the default painting behaviour of wheel scroll event on JScrollPane

查看:92
本文介绍了如何在JScrollPane上禁用滚轮滚动事件的默认绘制行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近购买了这本书肮脏的富客户端,我发现它非常有用和有趣。在本书的一个例子的基础上,我尝试实现一个自定义ScrollPane,它在要显示的组件的视图底部显示一个阴影。我最终得到了以下代码。它工作但不完美。特别是当我通过拖动滚动条滚动窗格时,一切正常,绘画非常流畅。但是当我用鼠标滚动滚动时,阴影闪烁,我不明白为什么。任何人都可以帮助我吗?

I recently purchased the book Filthy Rich Clients and i found it really useful and fun. Building on one example from the book i tried implementing a custom ScrollPane that displays a "shadow" on the bottom of its view over the component to be displayed. I ended up with the code below. It works but not perfectly. Specifically when i scroll the pane by dragging the scroll bar everything works ok and the painting is really smooth. But when i scroll with the mouse scroll the shadow flickers and i have no idea why. Can anyone help me?

编辑:滚动窗格中的任何组件都会发生同样的事情。编辑代码以显示两个框架以查看问题。

编辑2:我已将问题与滚动窗格处理的方式隔离开来鼠标滚轮事件。滚动滚动窗格时,根据滚动的方向稍微向上或向下复制视口的内容,然后绘制进入视图的区域。我的代码使整个组件脏但是在组件移动了内容之后。所以你会立刻看到影子渐变不合适,直到重新发布。有关如何禁用此功能的任何想法?

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Container;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.RepaintManager;

public class Test {

    public static void main(String[] args) {
        JFrame f = new JFrame("Table");
        JFrame f1 = new JFrame("Text Area");
        Object[] names = new Object[] { "Title", "Artist", "Album" };
        String[][] data = new String[][] {
                { "Los Angeles", "Sugarcult", "Lights Out" },
                { "Do It Alone", "Sugarcult", "Lights Out" },
                { "Made a Mistake", "Sugarcult", "Lights Out" },
                { "Kiss You Better", "Maximo Park", "A Certain Trigger" },
                { "All Over the Shop", "Maximo Park", "A Certain Trigger" },
                { "Los Angeles", "Sugarcult", "Lights Out" },
                { "Do It Alone", "Sugarcult", "Lights Out" },
                { "Made a Mistake", "Sugarcult", "Lights Out" },
                { "Kiss You Better", "Maximo Park", "A Certain Trigger" },
                { "All Over the Shop", "Maximo Park", "A Certain Trigger" },
                { "Los Angeles", "Sugarcult", "Lights Out" },
                { "Do It Alone", "Sugarcult", "Lights Out" },
                { "Made a Mistake", "Sugarcult", "Lights Out" },
                { "Kiss You Better", "Maximo Park", "A Certain Trigger" },
                { "All Over the Shop", "Maximo Park", "A Certain Trigger" },
                { "Los Angeles", "Sugarcult", "Lights Out" },
                { "Do It Alone", "Sugarcult", "Lights Out" },
                { "Made a Mistake", "Sugarcult", "Lights Out" },
                { "Kiss You Better", "Maximo Park", "A Certain Trigger" },
                { "All Over the Shop", "Maximo Park", "A Certain Trigger" },
                { "Los Angeles", "Sugarcult", "Lights Out" },
                { "Do It Alone", "Sugarcult", "Lights Out" },
                { "Made a Mistake", "Sugarcult", "Lights Out" },
                { "Kiss You Better", "Maximo Park", "A Certain Trigger" },
                { "All Over the Shop", "Maximo Park", "A Certain Trigger" },
                { "Going Missing", "Maximo Park", "A Certain Trigger" } };
        JTable table = new JTable(data, names);
        f.getContentPane().add(new ShadowScrollPane(table));
        f1.getContentPane().add(new ShadowScrollPane(new JTextArea(20, 50)));
        RepaintManager.setCurrentManager(new RepaintManager(){
            @Override
            public void addDirtyRegion(JComponent c, int x, int y, int w, int h) {
                Container con = c.getParent();
                while (con instanceof JComponent) {
                    if (!con.isVisible()) {
                        return;
                    }
                    if (con instanceof ShadowScrollPane ) {
                        c = (JComponent)con;
                        x = 0;
                        y = 0;
                        w = con.getWidth();
                        h = con.getHeight();
                    }
                    con = con.getParent();
                }
                super.addDirtyRegion(c, x, y, w, h);
            }
        });
        f.pack();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
        f1.pack();
        f1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f1.setVisible(true);
    }

}

@SuppressWarnings("serial")
class ShadowScrollPane extends JScrollPane {

    private final int h = 50;
    private BufferedImage img = null;
    private BufferedImage shadow = new BufferedImage(1, h, BufferedImage.TYPE_INT_ARGB);

    public ShadowScrollPane(JComponent com) {
        super(com);
        Graphics2D g2 = shadow.createGraphics();
        g2.setPaint(new Color(50, 50, 50));
        g2.fillRect(0, 0, 1, h);
        g2.setComposite(AlphaComposite.DstIn);
        g2.setPaint(new GradientPaint(0, 0, new Color(0, 0, 0, 0f), 0, h, new Color(1, 1, 1, 0.6f)));
        g2.fillRect(0, 0, 1, h);
        g2.dispose();
    }

    @Override
    public void paint(Graphics g) {
        if (img == null || img.getWidth()!=getWidth() || img.getHeight() != getHeight()) {
            img = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
        }
        Graphics2D g2 = img.createGraphics();
        super.paint(g2);
        Rectangle bounds = getViewport().getVisibleRect();
        g2.scale(bounds.getWidth(), -1);
        int y = (getColumnHeader()==null)?0:getColumnHeader().getHeight();
        g2.drawImage(shadow, bounds.x, -bounds.y - y-h, null);
        g2.scale(1,-1);
        g2.drawImage(shadow, bounds.x, bounds.y + bounds.height-h+y, null);
        g2.dispose();
        g.drawImage(img, 0, 0, null);
    }
}


推荐答案

有你试过在ScrollPane对象上调用setWheelScrollingEnabled(false)吗?

Have you tried calling setWheelScrollingEnabled(false) on the ScrollPane object?

来自javadoc:


启用/禁用滚动
响应鼠标
滚轮的移动。轮子滚动由
默认启用。

Enables/disables scrolling in response to movement of the mouse wheel. Wheel scrolling is enabled by default.

在Savvas下面的评论后更新。

Update following the comment by Savvas below.

也许视口上的setScrollMode(int)方法可以帮助你。此方法将确定swing如何滚动视口。

Perhaps the "setScrollMode(int)" method on the viewport can help you. This method will determine how swing scrolls the viewport.

您可以使用getViewPort()方法直接从ScrollPane获取视口。
您有以下选择:

You can get the viewport directly from the ScrollPane with the getViewPort() method. You have the following options:

BLIT_SCROLL_MODE
BACKINGSTORE_SCROLL_MODE
SIMPLE_SCROLL_MODE

根据javadoc BLIT_SCROLL_MODE 将使用Graphics.copyArea所以也许试试其中一个。

According to the javadoc BLIT_SCROLL_MODE will use Graphics.copyArea so perhaps try one of the others.

这篇关于如何在JScrollPane上禁用滚轮滚动事件的默认绘制行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆