在我的JFrame上,我使用以下代码在面板上显示图像:
ImageIcon img= new ImageIcon("res.png"); jLabel.setIcon(img);
我想“自动调整大小”标签中的图片。确实,有时图像大小只有几个像素,有时更大。
有没有办法设置标签的大小,然后自动调整标签中图像的大小?
这是一个棘手的问题。你强调了一个事实,即你正在使用a JLabel来显示图像,这是标准的处理方式,但是却JLabel是一个复杂的小野兽,具有文本,图标以及文本的对齐和定位。
a JLabel
JLabel
如果你不需要所有这些额外的功能,我将为你自己创建一个能够绘制缩放图像的自定义组件…
下一个问题是,你如何缩放图像?你是否要保持图像的长宽比?是否要将图像“适合”或“填充”到可用空间。
@大卫是正确的。你应该尽可能避免Image#getScaledInstance使用它,因为它不是最快的,但是更重要的是,通常它也不提供最高的质量。
Image#getScaledInstance
适合与填充
以下示例非常简单(并且从我的代码库中借来了很多代码,因此可能还有些复杂;)。可以从后台缩放线程使用它,但是我将根据原始图像的潜在大小来做出决定。
public class ResizableImage { public static void main(String[] args) { new ResizableImage(); } public ResizableImage() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException ex) { } catch (InstantiationException ex) { } catch (IllegalAccessException ex) { } catch (UnsupportedLookAndFeelException ex) { } try { BufferedImage image = ImageIO.read(new File("/path/to/your/image")); JFrame frame = new JFrame("Test"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(new ScalablePane(image)); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } catch (Exception exp) { exp.printStackTrace(); } } }); } public class ScalablePane extends JPanel { private Image master; private boolean toFit; private Image scaled; public ScalablePane(Image master) { this(master, true); } public ScalablePane(Image master, boolean toFit) { this.master = master; setToFit(toFit); } @Override public Dimension getPreferredSize() { return master == null ? super.getPreferredSize() : new Dimension(master.getWidth(this), master.getHeight(this)); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Image toDraw = null; if (scaled != null) { toDraw = scaled; } else if (master != null) { toDraw = master; } if (toDraw != null) { int x = (getWidth() - toDraw.getWidth(this)) / 2; int y = (getHeight() - toDraw.getHeight(this)) / 2; g.drawImage(toDraw, x, y, this); } } @Override public void invalidate() { generateScaledInstance(); super.invalidate(); } public boolean isToFit() { return toFit; } public void setToFit(boolean value) { if (value != toFit) { toFit = value; invalidate(); } } protected void generateScaledInstance() { scaled = null; if (isToFit()) { scaled = getScaledInstanceToFit(master, getSize()); } else { scaled = getScaledInstanceToFill(master, getSize()); } } protected BufferedImage toBufferedImage(Image master) { Dimension masterSize = new Dimension(master.getWidth(this), master.getHeight(this)); BufferedImage image = createCompatibleImage(masterSize); Graphics2D g2d = image.createGraphics(); g2d.drawImage(master, 0, 0, this); g2d.dispose(); return image; } public Image getScaledInstanceToFit(Image master, Dimension size) { Dimension masterSize = new Dimension(master.getWidth(this), master.getHeight(this)); return getScaledInstance( toBufferedImage(master), getScaleFactorToFit(masterSize, size), RenderingHints.VALUE_INTERPOLATION_BILINEAR, true); } public Image getScaledInstanceToFill(Image master, Dimension size) { Dimension masterSize = new Dimension(master.getWidth(this), master.getHeight(this)); return getScaledInstance( toBufferedImage(master), getScaleFactorToFill(masterSize, size), RenderingHints.VALUE_INTERPOLATION_BILINEAR, true); } public Dimension getSizeToFit(Dimension original, Dimension toFit) { double factor = getScaleFactorToFit(original, toFit); Dimension size = new Dimension(original); size.width *= factor; size.height *= factor; return size; } public Dimension getSizeToFill(Dimension original, Dimension toFit) { double factor = getScaleFactorToFill(original, toFit); Dimension size = new Dimension(original); size.width *= factor; size.height *= factor; return size; } 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; } public double getScaleFactorToFill(Dimension masterSize, Dimension targetSize) { double dScaleWidth = getScaleFactor(masterSize.width, targetSize.width); double dScaleHeight = getScaleFactor(masterSize.height, targetSize.height); return Math.max(dScaleHeight, dScaleWidth); } public BufferedImage createCompatibleImage(Dimension size) { return createCompatibleImage(size.width, size.height); } public BufferedImage createCompatibleImage(int width, int height) { GraphicsConfiguration gc = getGraphicsConfiguration(); if (gc == null) { gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration(); } BufferedImage image = gc.createCompatibleImage(width, height, Transparency.TRANSLUCENT); image.coerceData(true); return image; } protected BufferedImage getScaledInstance(BufferedImage img, double dScaleFactor, Object hint, boolean bHighQuality) { BufferedImage imgScale = img; int iImageWidth = (int) Math.round(img.getWidth() * dScaleFactor); int iImageHeight = (int) Math.round(img.getHeight() * dScaleFactor); if (dScaleFactor <= 1.0d) { imgScale = getScaledDownInstance(img, iImageWidth, iImageHeight, hint, bHighQuality); } else { imgScale = getScaledUpInstance(img, iImageWidth, iImageHeight, hint, bHighQuality); } return imgScale; } protected BufferedImage getScaledDownInstance(BufferedImage img, int targetWidth, int targetHeight, Object hint, boolean higherQuality) { int type = (img.getTransparency() == Transparency.OPAQUE) ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB; BufferedImage ret = (BufferedImage) img; if (targetHeight > 0 || targetWidth > 0) { int w, h; if (higherQuality) { // Use multi-step technique: start with original size, then // scale down in multiple passes with drawImage() // until the target size is reached w = img.getWidth(); h = img.getHeight(); } else { // Use one-step technique: scale directly from original // size to target size with a single drawImage() call w = targetWidth; h = targetHeight; } do { if (higherQuality && w > targetWidth) { w /= 2; if (w < targetWidth) { w = targetWidth; } } if (higherQuality && h > targetHeight) { h /= 2; if (h < targetHeight) { h = targetHeight; } } BufferedImage tmp = new BufferedImage(Math.max(w, 1), Math.max(h, 1), type); Graphics2D g2 = tmp.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint); g2.drawImage(ret, 0, 0, w, h, null); g2.dispose(); ret = tmp; } while (w != targetWidth || h != targetHeight); } else { ret = new BufferedImage(1, 1, type); } return ret; } protected BufferedImage getScaledUpInstance(BufferedImage img, int targetWidth, int targetHeight, Object hint, boolean higherQuality) { int type = BufferedImage.TYPE_INT_ARGB; BufferedImage ret = (BufferedImage) img; int w, h; if (higherQuality) { // Use multi-step technique: start with original size, then // scale down in multiple passes with drawImage() // until the target size is reached w = img.getWidth(); h = img.getHeight(); } else { // Use one-step technique: scale directly from original // size to target size with a single drawImage() call w = targetWidth; h = targetHeight; } do { if (higherQuality && w < targetWidth) { w *= 2; if (w > targetWidth) { w = targetWidth; } } if (higherQuality && h < targetHeight) { h *= 2; if (h > targetHeight) { h = targetHeight; } } BufferedImage tmp = new BufferedImage(w, h, type); Graphics2D g2 = tmp.createGraphics(); g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint); g2.drawImage(ret, 0, 0, w, h, null); g2.dispose(); ret = tmp; tmp = null; } while (w != targetWidth || h != targetHeight); return ret; } } }