JPanel 图像仅在 paintComponent 循环结束后更新

JPanel Image only updates after the paintComponent loop ends

目前,我的 paintComponent 是这样的:

    @Override
    public void paintComponent(Graphics g) {
    super.paintComponent(g);
    System.out.println(choice);
    if(choice == 1)
    {   
        g.drawImage(img, 0, 0, getWidth(), getHeight(), this);

        System.out.println("\nImgWidth: " + img.getWidth()
                + "\nFrameWidth: " + getWidth()
                + "\nImgHeight: " + img.getHeight()
                + "\nFrameHeight: " + getHeight()
        );
    }
    else if (choice == 2)
    {
        scale = 3.0;
        while(currScale < scale){
            currScale += .1;
            System.out.println(currScale + "-" + scale);

            Graphics2D g2 = (Graphics2D)g;
            g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                            RenderingHints.VALUE_INTERPOLATION_BICUBIC);
            int w = getWidth(); 
            int h = getHeight(); 
            int imageWidth = img.getWidth(); 
            int imageHeight = img.getHeight(); 
            double x = (w - currScale * imageWidth)/2;
            double y = (h - currScale * imageHeight)/2; 
            AffineTransform at = AffineTransform.getTranslateInstance(x,y);
            at.scale(currScale, currScale);
            g2.drawRenderedImage(img, at); 
            try {
                Thread.sleep(100);
            } catch (InterruptedException ex) {}

        }
    }

}

当我忘记循环并只使用固定的比例值时,代码可以工作,但我希望它是动画的而不是立即缩放。我试过使用 Timer 替代方案,但没有任何显示,图像在 paintComponent 被触发且选项为 2 时消失。

使用 sleep 方法,缩放后的图像会显示出来,但只能在循环之后显示。在循环之前和循环期间,它仍然显示原始的完整图像。它运行起来就像循环的整个点(动画)毫无意义,因为变化只在它退出时发生。

感谢任何帮助。

此外,如果你们有人想知道我是如何搞砸计时器的,这是我的代码(它删除了原始图像并且根本不显示任何内容,但计时器确实终止了)

   else
    {
        scale = 3.0;
            timer = new Timer(500, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {

        if(currScale < scale){
            System.out.println(currScale + "-" + scale);
            currScale += .1;
            Graphics2D g2 = (Graphics2D)g;
            g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                            RenderingHints.VALUE_INTERPOLATION_BICUBIC);
        int w = getWidth();
        int h = getHeight();
        int imageWidth = img.getWidth();
        int imageHeight = img.getHeight();
        double x = (w - currScale * imageWidth)/2;
        double y = (h - currScale * imageHeight)/2;
        AffineTransform at = AffineTransform.getTranslateInstance(x,y);
        at.scale(currScale, currScale);
        g2.drawRenderedImage(img, at);
        }
                }


            });

         if(currScale > scale)
        {
             timer.stop();
        }
         else
         {
             timer.setRepeats(true);
             timer.setCoalesce(true);
             timer.start();  
         }
    }

这是我的 class 属性的片段:

 class loadImage extends JPanel {
 private int choice;
 double scale;
 double currScale = 1.0;
 BufferedImage img;
 //Timer timer; (if using the timer)

修复: 为了添加一些上下文,我使用了 Netbean 的 GUI-Builder。每次我需要使用 loadImage 的方法时,我都选择手动将面板类型转换为 loadImage class。

    public void ZoomIn() {
    double scale = 3.0;
    double scaleAddOn = 0.1;
    Timer timer;
    timer = new Timer(40, new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) 
        {
            double currScale;
            currScale = ((loadImage)imageArea).getCurrScale();
            if(currScale < scale)
            {
                ((loadImage)imageArea).setCurrScale(currScale + scaleAddOn);
            }
        }
    });

    if(((loadImage)imageArea).getCurrScale() > scale)
    {
         timer.stop();
    }
     else
     {
         timer.setRepeats(true);
         timer.setCoalesce(true);
         timer.start();  
     }
}    

再次感谢您的帮助。希望此页面对其他人也有用。

当您从 JPanel 创建绘图面板时,paintComponent 方法会绘制或绘图。句号。 paintComponent 方法什么都不做。没有Thread.sleep。没有计算。随便画。

因为你只提供了一个 paintComponent 方法,我只提供 DrawingPanel class。

package com.ggl.testing;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;

import javax.swing.JPanel;

public class DrawingPanel extends JPanel {

    private static final long serialVersionUID = 506794466435048661L;

    private double currScale;

    private int choice;

    private BufferedImage img;

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        System.out.println(choice);
        if (choice == 1) {
            g.drawImage(img, 0, 0, getWidth(), getHeight(), this);
            System.out.println("\nImgWidth: " + img.getWidth()
                    + "\nFrameWidth: " + getWidth() + "\nImgHeight: "
                    + img.getHeight() + "\nFrameHeight: " + getHeight());
        } else if (choice == 2) {
            Graphics2D g2 = (Graphics2D) g;
            g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                    RenderingHints.VALUE_INTERPOLATION_BICUBIC);
            int w = getWidth();
            int h = getHeight();
            int imageWidth = img.getWidth();
            int imageHeight = img.getHeight();
            double x = (w - currScale * imageWidth) / 2;
            double y = (h - currScale * imageHeight) / 2;
            AffineTransform at = AffineTransform.getTranslateInstance(x, y);
            System.out.println("Pass");
            at.scale(currScale, currScale);
            System.out.println("Pass");
            g2.drawRenderedImage(img, at);
            System.out.println("Pass");
        }
    }

    public double getCurrScale() {
        return currScale;
    }

    public void setCurrScale(double currScale) {
        this.currScale = currScale;
        repaint();
    }

    public int getChoice() {
        return choice;
    }

    public void setChoice(int choice) {
        this.choice = choice;
    }

    public BufferedImage getImg() {
        return img;
    }

    public void setImg(BufferedImage img) {
        this.img = img;
    }

}

您可以使用 Runnable class 或 Swing Timer 来更新 currScale 值。