为什么 repaint() 从未调用 PaintComponent() ?

发布于 2024-11-05 08:10:08 字数 4890 浏览 0 评论 0原文

我一直在开发一个将自定义 JComponent 绘制到 JLayeredPane 上的程序,但是对组件上的所有 repaint() 调用似乎都没有执行任何操作,但在重新调整窗口大小时会自动调用 PaintComponent 方法。

我一直在遵循这里给出的一些建议: 调用过paint()/paintComponent()?

为什么从未 解决方案似乎解决了我的问题,更新 EDT 上的 swing 组件,在调用 repaint() 之前手动设置组件大小,在覆盖的 PaintComponent() 中调用 super.paintComponent(g) 并在添加新组件后在框架上调用 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()));
    }

}

I've been working on an program that draws custom JComponents onto a JLayeredPane however all calls to repaint() on the components seem to do nothing yet the paintComponent method is invoked automatically when the window is re-sized.

I have been following some of the advice given here:
Why is paint()/paintComponent() never called?

But none of the solutions seem to fix my problem, update swing components on the EDT, setting component size manually before calling repaint(), calling super.paintComponent(g) in the overridden paintComponent() and calling revalidate() on the frame after adding new components (although this is clearly no the issue in this case)

Any ideas what could be stopping the call? Thanks in advance :)

Here is the code for the View and the SVGElementContainer, view.setFile() is the entry-point as it is invoked when a new document needs to be displayed.

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()));
    }

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

淡笑忘祈一世凡恋 2024-11-12 08:10:08

我看到您正在调用 setOpaque(false)。从 setOpaque javadoc 中,强调我的:

如果为 true,则组件将绘制其边界内的每个像素。否则,组件可能无法绘制其部分或全部像素,从而允许底层像素显示出来。

这个“可能”是在 repaint() 调用期间第一次调用后 PaintComponent() 没有被调用的原因。 Swing 可以判定组件没有“改变”,因此不需要重新绘制。

I see that you're calling setOpaque(false). From the setOpaque javadoc, emphasis mine:

If true the component paints every pixel within its bounds. Otherwise, the component may not paint some or all of its pixels, allowing the underlying pixels to show through.

That "may" be the cause of paintComponent() not being called after the first time during a repaint() call. Swing can decide that the component has not "changed", and thus does not need repainting.

谢绝鈎搭 2024-11-12 08:10:08

在调用repaint()之前手动设置组件大小,在重写的paintComponent()中调用super.paintComponent(g)并在添加新组件后在框架上调用revalidate()

您的代码在这些概念上是错误的。

a) 切勿调用 setSize() 方法。这是布局管理器的工作。您应该通过重写 getPreferredSize() 等方法来向布局管理器提供提示,以返回组件的首选大小

b) 不要重写 revalidate() 方法。该技巧的要点是使用如下代码:

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

但我真的不知道你的所有代码应该做什么,所以我无法确定你的代码是否有意义。我还发现你扩展 JLayeredPane 很奇怪。

setting component size manually before calling repaint(), calling super.paintComponent(g) in the overridden paintComponent() and calling revalidate() on the frame after adding new components

Your code is wrong on these concepts.

a) never invoke the setSize() method. That is the job of the layout manager. You should be providing hints to the layout manager by overriding methods like getPreferredSize() to return the preferred size of your component

b) don't override the revalidate() method. The point of that tip is to use code like:

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

But I don't really know what all your code is supposed to do so I can't tell for sure if your code makes sense. I also find it strange that you are extending a JLayeredPane.

惜醉颜 2024-11-12 08:10:08

我可以看到扩展 JPanel 来获取缓冲和 UI 委托,但不透明度取决于 L&F 。相反,您可能应该从 JComponent 开始并实现 EventListenerList 为您的(假设的)SVGEvent 提供管道。

I can see extending JPanel to get the buffering and UI delegate, but the opacity is L&F dependent. Instead, you should probably start with JComponent and implement the EventListenerList plumbing for your (hypothetical) SVGEvent.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文