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 值。
目前,我的 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 值。