带有背景图像和剪切矩形的JTextPane问题

时间:2011-06-18 11:30:49

标签: java image swing paintcomponent

我有Swing的问题,我只是找不到原因。我有一个JTextPane,已扩展为显示背景图像。这可以是光栅图像(通过标准Java API显示)或SVG矢量图像(通过SVG Salamander显示)。

由于我希望文本窗格的顶部区域用作不显示任何文本的边距,我执行以下操作:我覆盖paintComponent(),绘制背景图像,然后调用super.paintComponent( )以便显示文本等,最后我再次绘制一块背景图像,但是使用剪切矩形仅覆盖上边距区域中的文本。

除了我一直在争吵的小故障外,这种方法完全正常:使用光栅图像,如果我在文本窗格中选择文本,则删除文本而不是突出显示。也就是说,当我选择文本时,背景图像显示在我选择的部分上。我不明白为什么会这样,因为在super.paintComponent()之前调用绘制图像的第一个调用,第二个调用有一个剪切矩形,所以它只绘制边缘,如果我不做,一切正常做出选择。一些额外的线索:

  • 我知道这是与第二次电话有关的事情,因为如果我评论它,我没有这个问题(那时我没有余量)。
  • 奇怪的是,当背景是矢量图像时,不会发生光栅图像。

这是我的paintComponent()方法的代码:

public void paintComponent(Graphics g)
{
    Rectangle rect = null;
    if ( rasterBackgroundImage != null )
    {
        rect = getVisibleRect();
        g.drawImage(rasterBackgroundImage.getImage(),rect.x,rect.y,rect.width,rect.height,this);
    }
    if ( vectorBackgroundImage != null )
    {
        rect = getVisibleRect();
        vectorBackgroundImage.setPreferredSize(new Dimension(rect.width,rect.height));
        vectorBackgroundImage.setScaleToFit(true);
        vectorBackgroundImage.paintIcon(this, g, rect.x, rect.y);
    }

    super.paintComponent(g);

    //if we want a non-scrolling top margin
    if ( rasterBackgroundImage != null )
    {
        g.setClip(rect.x,rect.y,rect.width,getMargin().top);
        g.drawImage(rasterBackgroundImage.getImage(),rect.x,rect.y,rect.width,rect.height,this);
    }
    if ( vectorBackgroundImage != null )
    {
        g.setClip(rect.x,rect.y,rect.width,getMargin().top);
        vectorBackgroundImage.setPreferredSize(new Dimension(rect.width,rect.height));
        vectorBackgroundImage.paintIcon(this, g, rect.x, rect.y);
    }

}

如果有人想看看全班,请点击此处:http://code.google.com/p/aetheria/source/browse/trunk/age/src/eu/irreality/age/swing/FancyJTextPane.java?r=301

请注意,我不是要求修复,因为问题似乎是与其他类的交互。这就是为什么我没有提供SSCCE:我试图建立一个,但如果我孤立地使用这个类......它实际上是可行的。我无法在整个系统之外重现问题,我不知道哪个交互产生它。但我会非常感谢任何人提供指示我指向正确方向的提示 - 也许有人之前已经看过这种事情并且可以找到可能的原因......

更新:我已经设法通过停止使用setClip()来解决此问题。我发现这个答案建议不要在paintComponent()中使用setClip():java swing clipping problem

我现在不是使用剪切矩形,而是创建一个子图像,其中包含我想在边距上绘制的图像的顶部,并直接绘制它而不调用setClip()。它可能是非常低效的,因为当一个应该足够时,我将两个图像存储在内存中,但至少它是Works(tm)。如果有人对看到这个黑客感到好奇,那就在这里(目前代码有点脏):http://code.google.com/p/aetheria/source/browse/trunk/age/src/eu/irreality/age/swing/FancyJTextPane.java?r=305

如果有人能够找出确切的原因,为什么以这种方式使用setClip()会导致这些问题,或者知道解决这个问题的有效方法,那将会很有趣。感谢所有的答案! :)

2 个答案:

答案 0 :(得分:3)

如果存在JLabelHow To Use Icon,为什么还要使用paintComponent(s)来绘制图像,其他有价值的信息在Performing Custom Painting中描述并在2D Graphics中扩展,吨示例here2D-Graphics-GUI

答案 1 :(得分:3)

除了@ mKorbel的有用链接,这里有一些想法:

  • 检查父容器的布局,注意BorderLayout的{​​{1}}和[{1}}的{​​{1}}的插入和默认设置。正如您所观察到的,对比色可以提供帮助。

  • 在父JFrame上,pack()应至少调用一次,因为它会导致此FlowLayout的大小适合其子组件的首选大小和布局。“

  • 严格检查JPanel在一个案例中的使用情况,而不是另一个案例,并指出您可能需要Window以及Window

  • 查看How to Use Editor Panes and Text Panes中的示例。

  • 另外,请考虑De Morgan's laws是否可以简化setPreferredSize()方法中的谓词:

    revalidate()