【问题标题】:Wrong getClipBounds in combination with JScrollPane错误的 getClipBounds 与 JScrollPane 结合使用
【发布时间】:2014-06-15 20:16:34
【问题描述】:

也许我遇到了错误或更可能做错了什么;) 我尝试使用JScrollPanel 翻译用户绘制的JPanel 的内容。在面板里面我想通过Graphics类getClipBounds方法访问可视区域来提高渲染性能。

在 SO 上搜索会带来很多关于 JScrollPane 的结果,但没有提到剪辑边界的问题。谷歌也一样。

用户绘制的面板

import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;

public class Content extends JPanel {
    @Override
    protected void paintChildren(Graphics g) {
        super.paintChildren(g);
        // intense clip bounds dependent rendering here
        System.out.println(g.getClipBounds());
    }
    @Override
    public Dimension getPreferredSize() {
        return new Dimension(2000,2000);
    }
}

主机设置

import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import java.awt.BorderLayout;

public class ClipBoundsIssue {
    private JFrame frame;
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    ClipBoundsIssue window = new ClipBoundsIssue();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
    public ClipBoundsIssue() {
        frame = new JFrame();
        frame.setBounds(100, 100, 450, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JScrollPane scrollPane = new JScrollPane();
        frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
        Content content = new Content();
        scrollPane.setViewportView(content);
    }
}

重现

只需运行代码,移动其中一个滚动条并检查System.out 的控制台输出。下图描述了在 x 轴上滚动条。

实际System.out 结果

产生了以下结果

java.awt.Rectangle[x=0,y=0,width=416,height=244]
java.awt.Rectangle[x=416,y=0,width=16,height=244]
java.awt.Rectangle[x=432,y=0,width=15,height=244]
java.awt.Rectangle[x=447,y=0,width=16,height=244]
java.awt.Rectangle[x=463,y=0,width=15,height=244]

预期结果

我本来希望边界的宽度保持不变。但它从 416 变为 16。

现在的问题是

有人知道为什么会发生这种情况,或者如何避免吗?

丢弃的 WAs

一种可能的解决方法是查找视口的视界。但如果可能的话,我想避免 Content 类进行任何此类查找。另一种选择是将信息传递给Content 类,但我也想避免这种情况。

【问题讨论】:

  • 检查了类似的问题here; Graphics 上下文中的某些元素可能会随着绘制链的每次行程而改变。批判性地检查依赖剪辑区域的必要性可能会有所帮助。
  • @trashgod 哦,我会看看它并重新评估...

标签: java swing jscrollpane java-2d clip


【解决方案1】:

我本来希望边界的宽度保持不变。

为什么?太简单了,很难解释,但让我试试。

当您滚动时,如果您缓慢滚动,则 JPanel 仅出现一小部分新部分。

产生的输出绝对正确:

java.awt.Rectangle[x=0,y=0,width=416,height=244]控件第一次显示,需要完全重绘

java.awt.Rectangle[x=416,y=0,width=16,height=244]您向右滚动了 16 个像素,因此必须重新绘制控件的窄条。

您必须了解这些坐标与您的控件相关,该控件的大小设置为 2000x2000 像素。

尝试滚动使用此代码创建的窗口,您将看到我在说什么:

import javax.swing.*;
import java.awt.*;
import java.util.Random;

public class ScrollPaneRepaintDemo extends JPanel {
    public ScrollPaneRepaintDemo() {
        setPreferredSize(new Dimension(2000,2000));
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.add(new JScrollPane(new ScrollPaneRepaintDemo()));
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    @Override protected void paintComponent(Graphics g) {
        Rectangle clip = g.getClipBounds();
        g.setColor(new Color(new Random().nextInt()));
        g.fillRect(clip.x, clip.y, clip.width, clip.height);
    }
}

顺便说一句——它之所以如此有效是因为 JPanel 的内部实现。如果您改为扩展 JComponent,则整个视口将被剪裁。我还补充说,JPanel 在调整大小时会完全重新绘制,它的优化仅适用于滚动。

【讨论】:

    猜你喜欢
    • 2011-05-28
    • 1970-01-01
    • 2021-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多