这是一个困扰我几个小时的问题,我 自己无法找到解决方案……
我在网上发现了类似的话题,但是我找不到 很好的解释并且尽可能简单的解决方案的完全相同的问题。我也 看过EDT和SwingWorker API文档,但对 我来说太复杂了:(
所以,让我们说清楚。我有一个带有JLabel的简单JFrame,其中 包含我的图像:
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(); } } }
It’s invoked by this piece of code:
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启动但从未更新)。
我对此将无济于事。带有适当 解释的简单,有效的示例 将是最受赞赏的;)
问候!
就个人而言,我可以在将其应用于标签之前调整其大小,或者使用aJPanel进行绘画。JLabel必须拖延很多功能。
举例来说,您遇到的问题是您实际上是在使用 该图像setIcon来设置图像,但是却 在其顶部paintComponent绘制了另一个(初始)图像
您的自定义标签将aImageIcon作为初始参数并将其绘制为初始参数
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); } }
You initialise it as such…
label = new MyJLabel(new ImageIcon(img));
It should be noted that if you used the Icon support of JLabel, this…
Icon
JLabel
label.setPreferredSize(dims);
会无关紧要,因为JLabel会使用图标的大小来确定其 首选的大小……但无论如何……
然后,使用此按钮更新图标。
img = image; if (label != null) { label.setIcon(new ImageIcon(img)); label.repaint(); }
应该指出的是,根据您的示例,这实际上是在EDT之外调用的,这很危险,并可能导致油漆变脏。
但setIcon永远不会改变的价值img范围内MyLabel,所以当你的paintComponent方法被调用时,你实际上是画了你的图标 已经在更新提供…
paintComponent
// Paint the new Icon super.paintComponent(g); // Paint the old/initial image... g.drawImage(img.getImage(), 0, 0, getWidth(), getHeight(), this);
Updated
就个人而言,我要做的是使用a之类的东西创建一个自定义组件,JPanel并根据 面板的当前大小缩放原始图像,例如……
现在,通常情况下,在执行图像缩放时,我更喜欢使用Java中演示的分治方法:维护JPanel 背景图像的宽高比,但是在此示例中,我只是AffineTransform为了简单起见使用
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; } } }