在另一个组件中绘制外来组件(即属于不同框架的内容窗格)

时间:2011-03-11 15:38:07

标签: java swing paint paintcomponent

你好。 我想绘制一个外来组件(即属于不同框架的内容窗格),我们称之为框架B,在框架A的组件内。

问题是当我绘制组件时,它也被绘制在框架A的内容窗格中,当框架被重新调整大小时,它也会闪烁或者全部变得丑陋(即组件内部出现一些蓝色方块,等等。如果我试图在绘画之前缩放或翻译外来组件,问题就会变得更加明显。

过了一会儿,我把它分类了,我想。但是我对这个解决方案感觉不太好,出于某些原因我相信可能会有更好的解决方案,更合适的解决方案。我需要你。 :)

这个问题更多的是要求解释为什么外来组件被错误地绘制而没有在组件内部涂料之前和之后操纵它的双缓冲特征。例如,使用任何一对 setDoubleBuffered(false)和setDoubleBuffered(true) 要么 disableDoubleBuffering(jP)和enableDoubleBuffering(jP)

分别在调用外部组件的paint方法之前和之后。

提前谢谢你。显示问题的SSCCE如下所示。


import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.io.IOException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.RepaintManager;

public class PaintForeignComponentSSCCE extends JFrame
{
    public static void main(String[] args) throws IOException
    {
        //foreign panel
        JPanel fp = new JPanel();
        fp.setBackground(Color.PINK);
        fp.setPreferredSize(new Dimension(200, 300));
        //component in which the foreign panel is painted
        ForeignComponentPainter fcp = new ForeignComponentPainter(fp);
        fcp.setPreferredSize(new Dimension(600, 600));
        //main frame's content
        JPanel contentPane = new JPanel();
        contentPane.setBackground(Color.BLUE);
        contentPane.add(fcp);
        //main frame
        JFrame f = new PaintForeignComponentSSCCE();
        f.setContentPane(contentPane);
        f.setSize(700, 500);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);             
        //foreign panel frame
        JFrame fpf = new JFrame();
        JPanel panelFrameContent = new JPanel();
        panelFrameContent.add(fp);
        fpf.setContentPane(panelFrameContent);
        fpf.setSize(400, 400);
        fpf.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        fpf.setVisible(true);
    }
}

class ForeignComponentPainter extends JButton
{
    private static final long serialVersionUID = 1L;
    private JPanel jP;

    public ForeignComponentPainter(JPanel jP)
    {
        super();
        this.jP = jP;
    }

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.drawString("OIOI", 50, 50);
        //g2.translate(100, 50);
        //g2.scale(.5, .5);
//      jP.setDoubleBuffered(false);
//      disableDoubleBuffering(jP);
        jP.paint(g2);
//      jP.setDoubleBuffered(true);
//      enableDoubleBuffering(jP);
        //g2.scale(1/.5, 1/.5);
    }   
    public static void disableDoubleBuffering(Component c)
    {
        RepaintManager currentManager = RepaintManager.currentManager(c);
        currentManager.setDoubleBufferingEnabled(false);
    }
    public static void enableDoubleBuffering(Component c)
    {
        RepaintManager currentManager = RepaintManager.currentManager(c);
        currentManager.setDoubleBufferingEnabled(true);
    }
}

与SSCCE示例无关。 以下与问题本身无关。 这段代码用于演示如何在组件中实现Printable,我也想以打印预览方式呈现该组件。打印调用组件的绘制(如下所示)。


public int print(Graphics g, PageFormat pageFormat, int pageIndex)
{ 
   if(pageIndex >= pageHeights.size()) 
      return NO_SUCH_PAGE; 
   int savedPage = currentPageIndex; 
   currentPageIndex = pageIndex; 
   Graphics2D g2 = (Graphics2D) g; 
   paint(g2); 
   currentPageIndex = savedPage; 
   return PAGE_EXISTS; 
} 

1 个答案:

答案 0 :(得分:2)

抱歉,我无法直接解决您的问题,但可以通过对常见模型有两种不同的观点来避免它。如How to Write a Document Listener所示,可以更新Document的多个view。您的模型和视图可能会有所不同,但这个概念仍然适用。

附录:

  

我认为这就是我现在正在做的事情,不是吗?我有一个模型,即'外国'组件,两个视图一个做默认油漆和第二个自定义油漆。

不,你有一个视图更新另一个;你需要两个视图来响应一个模型。相关的example可能会提供一些见解。

  

我仍然对这种错误绘画的原因提出建议感兴趣。

尝试交错两个组件的更新是IMO,从根本上是有缺陷的;它颠覆了Painting in Swing的正常过程。在我的平台上,我只看到一个非常短暂的闪烁,没有不定的绘画。虽然有可能在一个系统上获得满意的结果,但这种安排在实施过程中是不可靠的。

  

是一个简单的重新调用标签的调用,放在ModelObserver的{​​{1}}方法中适当的解决方案吗?

是的,update(),但应该在repaint()的{​​{3}}中完成:

View