1

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

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

过了一会儿,我整理了一下,我想。但是我对这个解决方案感觉不太好,出于某种原因,我相信可能会有更好的解决方案,更合适的解决方案。在这里我需要你。:)

这个问题更多的是要求解释为什么外部组件被错误地绘制而没有在组件内部绘制之前和之后操纵它的双缓冲功能。例如,使用任何一对 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,我还想以打印预览方式呈现该组件。print 调用组件的paint(如下图)。


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; 
} 
4

1 回答 1

2

抱歉,我无法直接解决您的问题,但可以通过对一个通用模型有两种不同的观点来避免它。如如何编写文档侦听器中所示,可以更新多个视图Document您的模型和视图可能不同,但该概念仍然适用。

附录:

我想这就是我现在正在做的事情,不是吗?我有一个模型,即“外部”组件,以及两个视图,一个是默认绘制,第二个是自定义绘制。

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

我仍然对有关这幅错误绘画原因的建议感兴趣。

IMO 将两个组件的更新交错进行的尝试从根本上是有缺陷的。它颠覆了Swing中正常的绘画流程。在我的平台上,我只看到一个非常短暂的闪烁,没有偶然的绘画。尽管有可能在一个系统上获得令人满意的结果,但这种安排在不同的实现中是不可靠的。

对标签重绘的简单调用,放在ModelObserver'update()方法中是适当的解决方案吗?

是的repaint(),但是应该在ButtonHandlerfor中完成View

private class ButtonHandler implements ActionListener {

    @Override
    public void actionPerformed(ActionEvent e) {
        PieceButton pb = (PieceButton) e.getSource();
        icon.color = pb.piece.color;
        label.repaint();
        model.check(pb.piece);
    }
}
于 2011-03-11T17:25:58.807 回答