也许我遇到过一个错误,或者更多可能做错了;)
我尝试使用JPanel
翻译用户JScrollPanel
的内容。在面板内部,我希望通过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。
有人知道为什么会这样,或者如何避免?
可能的解决方法是查找视口的视图边界。但是如果可能的话,我想避免Content
类进行任何此类查找。另一种选择是将信息传递到Content
类,但我也想避免这样做。
答案 0 :(得分: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在调整大小时完全重新绘制,其优化仅用于滚动。