JScrollNavigator
组件,以便在我嵌入在JScrollPane
中的大型“画布式”CAD组件上提供导航窗口。我尝试调整
JScrollNavigator
以绘制画布的缩略图,以向用户提供一些附加上下文。但是,这样做会导致我的应用程序主框架渲染损坏。具体而言,调用位于视口组件上(即我的主画布)的paint(Graphics)
方法,传递由BufferedImage
创建的Graphics
对象会导致后续显示发生损坏。如果我注释掉这行代码,一切正常。以下是
JScrollNavigator
的重写paintComponent
方法:@Override
protected void paintComponent(Graphics g) {
Component view = jScrollPane.getViewport().getView();
BufferedImage img = new BufferedImage(view.getWidth(), view.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
// Paint JScrollPane view to off-screen image and then scale.
// It is this action that causes the display corruption!
view.paint(g2d);
g2d.drawImage(img, 0, 0, null);
Image scaled = img.getScaledInstance(getWidth(), getHeight(), 0);
super.paintComponent(g);
g.drawImage(scaled, 0, 0, null);
}
有人能提供损坏的原因吗?我本以为在离屏图像上绘制不会对现有的绘制操作产生影响。
编辑
提供一些额外的细节: JScrollNavigator
是一个子面板,位于 JSplitPane
的左侧。与导航器相关联的 JScrollPane
位于右侧。 "corruption" 导致拆分器不再呈现,滚动条不可见(它们呈白色)。如果我调整 JFrame
的大小,则 JMenu
部分也变为白色。如果我试图使用导航器或与滚动条交互,则它们变为可见,但分隔符仍然是白色的。就好像各种组件的不透明设置受到了视口视图渲染到离屏图像的影响一样。
此外,如果我将 JScrollNavigator
显示在完全独立的 JDialog
中,一切都正常工作。
编辑 2
我可以通过以下方式 持续地 复现问题:
将 JMenuBar
添加到 mFrame
中:
JMenuBar bar = new JMenuBar();
bar.add(new JMenu("File"));
mFrame.setJMenuBar(bar);
在
JScrollNavigator
的 main()
方法中,将以下内容替换:jsp.setViewportView(textArea);
使用以下方式:
jsp.setViewportView(new JPanel() {
{
setBackground(Color.GREEN);
setBorder(BorderFactory.createLineBorder(Color.BLACK, 5));
}
});
确保将JScrollNavigator
作为一个面板嵌入到mFrame
中,而不是作为一个独立的JDialog
出现:
mFrame.add(jsp, BorderLayout.CENTER);
mFrame.add(nav, BorderLayout.NORTH);
现在应用程序运行时,
JMenuBar
不再可见;将视图(即绿色的JPanel
带有粗黑边框)绘制到BufferedImage.createGraphics()
返回的Graphics2D
上实际上似乎是从JFrame的左上角开始呈现在屏幕上,因此遮挡了其他组件。这只发生在将JPanel
用作视口视图而不是其他组件(如JTextArea
、JTable
等)的情况下。编辑3:
看起来这个人也遇到了同样的问题(尽管没有发布解决方案):http://www.javaworld.com/community/node/2894/ 编辑4:
以下是导致Edit 2中所描述的可重现错误的
main
和paintComponent
方法:public static void main(String[] args) {
JScrollPane jsp = new JScrollPane();
jsp.setViewportView(new JPanel() {
{
setBackground(Color.GREEN);
setBorder(BorderFactory.createLineBorder(Color.BLACK, 5));
}
});
JScrollNavigator nav = new JScrollNavigator();
nav.setJScrollPane(jsp);
JFrame mFrame = new JFrame();
JMenuBar bar = new JMenuBar();
bar.add(new JMenu("File"));
mFrame.setJMenuBar(bar);
mFrame.setTitle("JScrollNavigator Test");
mFrame.setSize(800, 600);
mFrame.setLayout(new GridLayout(1, 2));
mFrame.add(jsp);
mFrame.add(nav);
Dimension screenDim = Toolkit.getDefaultToolkit().getScreenSize();
mFrame.setLocation((screenDim.width - mFrame.getSize().width) / 2, (screenDim.height - mFrame.getSize().height) / 2);
mFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mFrame.setVisible(true);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Component view = jScrollPane.getViewport().getView();
if (img == null) {
GraphicsConfiguration gfConf = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
img = new BufferedImage(view.getWidth(), view.getHeight(), BufferedImage.TYPE_INT_ARGB);
}
Graphics2D g2d = img.createGraphics();
view.paint(g2d);
Image scaled = img.getScaledInstance(getWidth(), getHeight(), 0);
g.drawImage(scaled, 0, 0, null);
}
编辑5
似乎其他人也无法重现确切的问题。我建议大家运行在这里粘贴的代码。当我第一次运行此示例时,我看到以下内容:
既未绘制JScrollNavigator也未绘制JMenuBar;这些框架区域是透明的。
调整大小后,我看到以下内容:
JMenuBar仍未被绘制,并且似乎JPanel曾经在(0,0)处呈现过(JMenuBar应该在此处)。view.paint调用paintComponent中的是直接原因。
paintComponent
方法的开头调用super.paintComponent(g);
即可。 - Xeon