我正在使用此处JScrollNavigator
描述的组件,以便在我嵌入在.JScrollPane
我试图调整JScrollNavigator
以绘制画布的缩略图,以便为用户提供一些额外的上下文。但是,这样做会导致我的应用程序主框架的呈现损坏。具体来说,是调用paint(Graphics)
视口组件(即我的主画布)的动作,传入Graphics
由创建的对象BufferedImage
导致后续显示损坏;如果我将此行注释掉,一切正常。
下面是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
关联的位于右侧。“损坏”导致拆分器不再被渲染并且滚动条不可见(它们看起来是白色的)。如果我调整大小JFrame
,该JMenu
部分也会变成白色。如果我尝试使用导航器或与滚动条交互,它们会变得可见,但拆分器仍然是白色的。就好像各种组件的不透明设置受到了将视口视图渲染到屏幕外图像的影响。
此外,如果我将其JScrollNavigator
显示在一个完全独立的JDialog
中,则一切正常。
编辑 2
我可以通过执行以下操作来一致地重现该问题:
添加JMenuBar
到mFrame
:
JMenuBar bar = new JMenuBar();
bar.add(new JMenu("File"));
mFrame.setJMenuBar(bar);
在替换main()
方法中:JScrollNavigator
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
带有粗黑边框的绿色)绘制到Graphics2D
返回的行为BufferedImage.createGraphics()
实际上似乎是在屏幕上渲染它,可能是从 JFrame 的左上角开始,从而掩盖了其他组件。这似乎只在 aJPanel
用作视口视图时才会发生,而不是其他组件,例如JTextArea
,JTable
等。
编辑 3
看起来这个人遇到了同样的问题(虽然没有发布解决方案):http ://www.javaworld.com/community/node/2894/
编辑 4
以下是导致编辑 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
是造成这种情况的直接原因。