gpt4 book ai didi

java - 如何正确刷新JFrame中的图像?

转载 作者:行者123 更新时间:2023-12-02 06:20:30 25 4
gpt4 key购买 nike

这个问题困扰了我几个小时,我自己无法找到解决方案......

我在网上找到了类似的主题,但我找不到完全相同的问题,并且没有很好的解释和尽可能简单的解决方案。我还查看了 EDTSwingWorker API 文档,但它对我来说太复杂了:(

那么,让我们进入正题吧。我有一个简单的 JFrame,里面有 JLabel,其中包含我的图像:

private static class MyJLabel extends JLabel {
private ImageIcon img = null;

public MyJLabel(ImageIcon img) {
super();
this.img = img;
}

@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(img.getImage(), 0, 0, getWidth(), getHeight(), this);
}
}

private static class MyJFrame extends JFrame implements Runnable {
private BufferedImage img = null;
private MyJLabel label = null;

public MyJFrame(BufferedImage image, String title) {
super(title);
img = image;
}

@Override
public void run() {
Dimension dims = new Dimension(img.getWidth(), img.getHeight());
dims = new Dimension(dims.width / 2, dims.height / 2);

label = new MyJLabel(new ImageIcon(img));
label.setPreferredSize(dims);

addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
label.repaint();
}
});
setLayout(new BorderLayout());
getContentPane().add(BorderLayout.CENTER, label);
setLocation(200, 200);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
pack();
setVisible(true);
}

public void changeImage(BufferedImage image) {
img = image;
if (label != null) {
label.setIcon(new ImageIcon(img));
label.repaint();
}
}
}

它是由这段代码调用的:

buffer = receiveImage(in); // download image

MyJFrame f = null;
javax.swing.SwingUtilities.invokeLater(f = new MyJFrame(buffer, "RDP"));

int x = 0;
while (x <= 15) {
txt.println("next"); // notify server that we are ready

while (true) { // wait for server
if (reader.readLine().equals("ready")) break;
}

buffer = receiveImage(in); // download image

// do some magic here and refresh image somehow :(
f.changeImage(buffer); // does not work!

x++;
}

不幸的是,我使用 changeImage 方法的方法不起作用 - 什么也没有发生(GUI 启动但从未更新)。

如果您能提供一点帮助,我将不胜感激。 简单,带有正确解释的工作示例将受到最赞赏;)

您好!

最佳答案

就我个人而言,我要么在将其应用到标签之前调整其大小,要么使用 JPanel来进行绘画。 JLabel有太多的功能拖着它。

举个例子,您遇到的问题是您实际上正在使用 setIcon设置图像,但使用 paintComponent在其顶部绘制另一个(初始)图像

您的自定义标签采用 ImageIcon作为初始参数并将其绘制为这样......

private static class MyJLabel extends JLabel {
private ImageIcon img = null;

public MyJLabel(ImageIcon img) {
super();
this.img = img;
}

@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(img.getImage(), 0, 0, getWidth(), getHeight(), this);
}
}

你这样初始化它......

label = new MyJLabel(new ImageIcon(img));

需要注意的是,如果您使用Icon支持JLabel ,这个...

label.setPreferredSize(dims);

JLabel 无关将使用图标大小来确定其首选大小...但无论如何...

然后你用这个更新图标..

img = image;
if (label != null) {
label.setIcon(new ImageIcon(img));
label.repaint();
}

需要指出的是,根据您的示例,这实际上是在 EDT 之外调用的,这是危险的,可能会导致油漆脏

但是setIcon永远不会改变 img 的值MyLabel内,所以当你的 paintComponent调用方法时,您实际上是在更新中提供的图标上绘画...

// Paint the new Icon
super.paintComponent(g);
// Paint the old/initial image...
g.drawImage(img.getImage(), 0, 0, getWidth(), getHeight(), this);

已更新

就我个人而言,我要做的是创建一个自定义组件,使用类似 JPanel 的东西。并根据当前面板的大小缩放原始图像,例如...

现在,通常,在执行图像缩放时,我更喜欢使用分而治之的方法,如 Java: maintaining aspect ratio of JPanel background image 中所示。 ,但对于这个例子,我只是使用了 and AffineTransform为了简单起见

Small Large

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.geom.AffineTransform;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class ScalableImageExample {

public static void main(String[] args) {
new ScalableImageExample();
}

public ScalableImageExample() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}

try {
ResizableImagePane pane = new ResizableImagePane();
pane.setImage(...);

JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(pane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException exp) {
exp.printStackTrace();
}
}
});
}

public class ResizableImagePane extends JPanel {

private Image img;

public ResizableImagePane() {
}

public void setImage(Image value) {
if (img != value) {
Image old = img;
this.img = value;
firePropertyChange("image", old, img);
revalidate();
repaint();
}
}

public Image getImage() {
return img;
}

@Override
public Dimension getPreferredSize() {
return img == null ? new Dimension(200, 200) : new Dimension(img.getWidth(this), img.getHeight(this));
}

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
Graphics2D g2d = (Graphics2D) g.create();

int width = getWidth();
int height = getHeight();

double scaleFactor = getScaleFactorToFit(new Dimension(img.getWidth(this), img.getHeight(this)), getSize());

int x = (int)((width - (img.getWidth(this) * scaleFactor)) / 2);
int y = (int)((height - (img.getHeight(this) * scaleFactor)) / 2);

AffineTransform at = new AffineTransform();
at.translate(x, y);
at.scale(scaleFactor, scaleFactor);
g2d.setTransform(at);
g2d.drawImage(img, 0, 0, this);
g2d.dispose();
}
}

public double getScaleFactor(int iMasterSize, int iTargetSize) {

return (double) iTargetSize / (double) iMasterSize;

}

public double getScaleFactorToFit(Dimension original, Dimension toFit) {

double dScale = 1d;

if (original != null && toFit != null) {

double dScaleWidth = getScaleFactor(original.width, toFit.width);
double dScaleHeight = getScaleFactor(original.height, toFit.height);

dScale = Math.min(dScaleHeight, dScaleWidth);

}

return dScale;

}

}

}

关于java - 如何正确刷新JFrame中的图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21070703/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com