1

カスタム JComponents を JLayeredPane に描画するプログラムに取り組んできましたが、コンポーネントの repaint() へのすべての呼び出しは何もしていないように見えますが、ウィンドウのサイズが変更されると、paintComponent メソッドが自動的に呼び出されます。

ここで与えられたアドバイスのいくつかに従っています: なぜ paint()/paintComponent() が呼び出されないのですか?

しかし、解決策のどれも私の問題を解決していないようです.EDTでswingコンポーネントを更新し、repaint()を呼び出す前にコンポーネントサイズを手動で設定し、オーバーライドされたpaintComponent()でsuper.paintComponent(g)を呼び出し、フレームでrevalidate()を呼び出します新しいコンポーネントの追加 (ただし、この場合は明らかに問題ではありません)

通話を停止している可能性のあるアイデアはありますか? 前もって感謝します :)

ビューと SVGElementContainer のコードは次のとおりです。view.setFile() は、新しいドキュメントを表示する必要があるときに呼び出されるエントリ ポイントです。

public class View extends JLayeredPane implements SVGViewport {

    private SVGDocument document;
    //Array list of the SVGElementContainer components
    private ArrayList<SVGElementContainer> elemContainers;
    private SVGFrame frame;
    private int elemCount;
    private Border viewBorder;
    private int borderWidth = 1;

    //panels displayed on the JLayeredPane
    private JPanel backgroundPanel;

    /** Creates a new view */
    public View(SVGFrame frame) {
        super();
        this.frame = frame;
        elemCount = 0;

        elemContainers = new ArrayList<SVGElementContainer>();
        viewBorder = BorderFactory.createLineBorder(Color.BLACK, borderWidth);
    }

    public float getViewportWidth() {
        return getWidth();
    }

    public float getViewportHeight() {
        return getHeight();
    }

    // paints all elements and adds them to the JLayeredPane
    public void paintAllElements(){

        System.out.println("Painting all elements");

        // Paint document
        for (SVGElement elem : document) {
            //only paint stylable (rect, line, circle) elements
            if (elem instanceof SVGStylable){
                //create a new SVGElementContainer
                SVGElementContainer newElemCont = new SVGElementContainer();

                //add component to JLayeredPane
                elemCount++;
                this.add(newElemCont, new Integer(elemCount + 1));

                //set the current element within its container and calls repaint() on the component
                System.out.println("Painting element #" + elemCount);
                newElemCont.setElement(elem);
                newElemCont.repaint();
            }
            else {
                System.out.println("Skip painting group element!");
            }
        }
    }

    /** Gets the document currently being displayed by the view. */
    public SVGDocument getDocument() {
        return document;
    }

    /** Sets the document that the view should display.
     *
     * @param document the document to set
     */
    public void setDocument(SVGDocument document) {
        this.document = document;
        //paintBackground();
        paintAllElements();
        revalidate();
    }

    public void revalidate(){
        //calls validate() on the frame in order to display newly added components
        frame.getContentPane().validate();
    }
}

public class SVGElementContainer extends JPanel{

    private SVGElement elem;

    public SVGElementContainer(){
        super();
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        System.out.println("PAINT METHOD CALLED!");
        paint2D((Graphics2D) g);
    }

    //paint the element onto this JComponent
    public void paint2D(Graphics2D g){
        if (!(elem instanceof SVGStylable)){
            System.out.println("Skipping non-stylable element!");
            return;
        }

        setOpaque(false);

        Shape shape = elem.createShape();

        // get fill stroke and width properties
        SVGStylable style = (SVGStylable) elem;
        SVGPaint fillPaint = style.getFill();
        SVGPaint strokePaint = style.getStroke();
        SVGLength strokeWidth = style.getStrokeWidth();

        // Fill the interior of the shape
        if (fillPaint.getPaintType() == SVGPaint.SVG_PAINTTYPE_RGBCOLOR) {
            g.setPaint(fillPaint.getRGBColor());
            g.fill(shape);
        }

        // Stroke the outline of the shape
        if (strokePaint.getPaintType() == SVGPaint.SVG_PAINTTYPE_RGBCOLOR) {
            Stroke stroke = new BasicStroke(strokeWidth.getValue());
            g.setStroke(stroke);
            g.setColor(strokePaint.getRGBColor());
            g.draw(shape);
        }
    }

    public void setElement(SVGElement elem){
        this.elem = elem;
        setComponentSize();
    }

    private void setComponentSize(){

        //this.setPreferredSize(new Dimension(
        //  (int)elem.getDocument().getWidth().getValue(),
        //  (int)elem.getDocument().getHeight().getValue()));

        this.setSize(new Dimension(
                (int)elem.getDocument().getWidth().getValue(),
                (int)elem.getDocument().getHeight().getValue()));
    }

}
4

3 に答える 3

2

repaint()を呼び出す前にコンポーネントのサイズを手動で設定し、オーバーライドされたpaintComponent()でsuper.paintComponent(g)を呼び出し、新しいコンポーネントを追加した後にフレームでrevalidate()を呼び出します。

あなたのコードはこれらの概念について間違っています。

a)setSize()メソッドを呼び出さないでください。それがレイアウトマネージャーの仕事です。getPreferredSize()などのメソッドをオーバーライドして、コンポーネントの推奨サイズを返すことにより、レイアウトマネージャーにヒントを提供する必要があります。

b)revalidate()メソッドをオーバーライドしないでください。そのヒントのポイントは、次のようなコードを使用することです。

panel.add( .... );
panel.revalidate();
panel.repaint();

しかし、私はあなたのすべてのコードが何をすることになっているのか本当にわからないので、あなたのコードが理にかなっているかどうかはわかりません。また、JLayeredPaneを拡張しているのも不思議です。

于 2011-05-05T20:32:20.677 に答える
2

setOpaque(false) を呼び出しているようです。setOpaque javadoc から、強調鉱山:

true の場合、コンポーネントは境界内のすべてのピクセルをペイントします。そうしないと、コンポーネントが一部またはすべてのピクセルを描画せず、下にあるピクセルが透けて見える可能性があります。

その「可能性」が、repaint() 呼び出し中に初めて paintComponent() が呼び出されない原因です。Swing は、コンポーネントが「変更」されていないと判断できるため、再描画は必要ありません。

于 2011-05-05T19:57:09.443 に答える
1

バッファリングと UI デリゲートを取得するために拡張していることがわかりますJPanelが、不透明度は L&F に依存します。代わりに、おそらく(仮説的な) の配管から始めてJComponent実装する必要があります。EventListenerListSVGEvent

于 2011-05-05T20:38:29.923 に答える