【问题标题】:Issue with JTextPane with background image and clipping rectangle带有背景图像和剪切矩形的 JTextPane 问题
【发布时间】:2011-06-18 11:30:48
【问题描述】:

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

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

除了我几天来一直在努力解决的一个小故障之外,这一切都很好:使用光栅图像,如果我在文本窗格中选择文本,文本将被删除而不是突出显示。也就是说,当我选择文本时,背景图像会显示在我选择的部分上。我不明白为什么会这样,因为绘制图像的第一个调用是在 super.paintComponent() 之前调用的,第二个调用有一个剪切矩形,所以它只在边距上绘制,如果我不这样做,一切正常t 做出选择。一些额外的线索:

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

这是我的 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()。这可能效率很低,因为我在内存中存储了两个图像,而一个应该足够了,但至少它可以工作(tm)。如果有人对看到这个 hack 感到好奇,就在这里(代码现在有点脏):http://code.google.com/p/aetheria/source/browse/trunk/age/src/eu/irreality/age/swing/FancyJTextPane.java?r=305

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

【问题讨论】:

  • 我有一种感觉,这个问题如果不能被隔离或复现,将很难解决。不需要矢量图的 M(中等长度)SCCE 怎么样?
  • 我会继续努力做一个。我试图这样做,但问题是它没有表现出故障。我不知道我对文本窗格执行的外部操作会导致这种行为,但我会继续寻找......
  • @Algorithm:请让我们知道事情进展如何。您可以在之前发布的相同位置发布代码并提供链接。如果你这样做,人们下载并运行它的机会比你发布 SSCCE 的机会要小,但我敢打赌,因为这似乎是一个有趣的问题。运气!
  • 我已经确认第二次调用会在选择文本时在图形剪辑之外绘制部分图像。例如,如果我让第一个调用以彩色绘制背景,第二个调用以黑白版本绘制图像,则选择文本会使背景的这些部分变为黑白。

标签: java image swing paintcomponent


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    • 检查父容器的布局,注意插入和默认值,例如BorderLayout 对应JFrame,FlowLayout 对应JPanel。正如您所观察到的,对比色会有所帮助。

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

    • 严格检查setPreferredSize()在一种情况下的使用,注意您可能需要revalidate()和repaint()。

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

    • 顺便说一句,考虑De Morgan's laws 是否可以简化set*BackgroundImage() 方法中的谓词:

      setOpaque(!(rasterBackgroundImage == null && vectorBackgroundImage == null));
      

    【讨论】:

    • 感谢您的有趣项目;对不起,如果这些建议是基本的。
    猜你喜欢
    • 1970-01-01
    • 2016-04-25
    • 2022-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-14
    • 1970-01-01
    • 2015-06-05
    相关资源
    最近更新 更多