1

ハローみんな。フレームAのコンポーネント内に、外部コンポーネント(つまり、別のフレームのコンテンツペインに属する)をペイントしたいので、それをフレームBと呼びます。

問題は、コンポーネントをペイントすると、フレームAのコンテンツペインにもペイントされることです。また、フレームのサイズを変更すると、ちらつくか、すべてが醜くなります(つまり、コンポーネント内で数回ペイントすると、青い四角がいくつか表示されます。など)。たとえば、ペイントする前に異物を拡大縮小または変換しようとすると、問題がより明確になります。

しばらくして仕分けしたと思います。しかし、私はこの解決策に満足していません。何らかの理由で、より良い解決策、より適切な解決策があるかもしれないと信じています。ここにあなたが必要です。:)

この質問は、コンポーネント内のペイントの前後にダブルバッファリング機能を操作せずに、外部コンポーネントが正しくペイントされない理由を説明するための呼び出しです。たとえば、setDoubleBuffered(false)とsetDoubleBuffered(true)のペア、またはdisableDoubleBuffering(jP)とenableDoubleBuffering(jP)のいずれかを使用します。

それぞれ、外部コンポーネントのペイントメソッドの呼び出しの前後。

前もって感謝します。問題を示す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; 
} 
4

1 に答える 1

2

申し訳ありませんが、あなたの質問に直接お答えすることはできませんが、共通のモデルについて 2 つの異なるビューを用意することで、質問を回避できる場合があります。How to Write a Document Listenerに示されているように、 の複数のビューを更新することができDocumentます。モデルとビューは異なる場合がありますが、概念は引き続き適用されます。

補遺:

それが今私がしていることだと思いますね。私は 1 つのモデル、つまり「外部」コンポーネントと、デフォルト ペイントと 2 番目のカスタム ペイントを行う 2 つのビューを持っています。

いいえ、別のビューを更新するビューがあります。1 つのモデルに対応する 2 つのビューが必要です。この関連するは、いくつかの洞察を提供するかもしれません。

この誤った絵の理由についての提案に今でも興味があります。

2 つのコンポーネントの更新をインターリーブしようとする試みは、IMO では根本的に欠陥があります。Swingでのペイントの通常のプロセスを覆します。私のプラットフォームでは、非常に短いちらつきだけが見られ、偶発的な絵は見られません。1 つのシステムで満足のいく結果を得ることができるかもしれませんが、この配置は実装間で信頼できません。

ModelObserverupdate()メソッドに配置されたラベルを再描画するための単純な呼び出しは適切な解決策ですか?

はい。ただし、 forrepaint()で実行する必要があります。ButtonHandlerView

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 に答える