почему paintComponent () никогда не вызывается repaint ()? - PullRequest
1 голос
/ 05 мая 2011

Я работал над программой, которая рисует пользовательские JComponents на JLayeredPane, однако все вызовы repaint () для компонентов, похоже, ничего не делают, но метод paintComponent вызывается автоматически при изменении размера окна.

Я следовал некоторым советам, данным здесь: Почему paint () / paintComponent () никогда не вызывается?

Но ни одно из решений, похоже, не решает мою проблему, обновляет компоненты свинга в EDT, устанавливает размер компонента вручную перед вызовом repaint (), вызывает super.paintComponent (g) в переопределенном paintComponent () и вызывает revalidate () для кадр после добавления новых компонентов (хотя в данном случае это явно не проблема)

Есть идеи, что могло бы остановить звонок? Заранее спасибо:)

Вот код для View и 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()));
    }

}

Ответы [ 3 ]

2 голосов
/ 06 мая 2011

установка размера компонента вручную перед вызовом repaint (), вызовом super.paintComponent (g) в переопределенном paintComponent () и вызовом revalidate () для фрейма после добавления новых компонентов

Ваш код неверен в этих понятиях.

a) никогда не вызывайте метод setSize ().Это работа менеджера по расположению.Вы должны предоставлять подсказки диспетчеру компоновки, переопределяя методы, такие как getPreferredSize (), чтобы вернуть предпочтительный размер вашего компонента

b), не переопределяйте метод revalidate ().Смысл этого совета - использовать код вроде:

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

Но я не знаю, что должен делать весь ваш код, поэтому я не могу точно сказать, имеет ли смысл ваш код.Мне также кажется странным, что вы расширяете JLayeredPane.

2 голосов
/ 05 мая 2011

Я вижу, что вы вызываете setOpaque (false).В javadoc setOpaque выделено:

Если true, компонент закрашивает каждый пиксель в пределах своих границ.В противном случае компонент может не закрасить некоторые или все свои пиксели , что позволяет просвечивать нижележащие пиксели.

Это может быть причиной того, что paintComponent () не вызывается после первого раза во время вызова repaint ().Swing может решить, что компонент не «изменился», и, следовательно, не требует перекраски.

1 голос
/ 06 мая 2011

Я вижу расширение JPanel для получения буферизации и делегата пользовательского интерфейса, но непрозрачность зависит от L & F.Вместо этого вам, вероятно, следует начинать с JComponent и применять EventListenerList для вашего (гипотетического) SVGEvent.

...