如何使JLabel与图像填充BorderLayout.CENTER

我有一个JFrame并将LayoutManager设置为BorderLayout然后继续添加我的JLabel图像。 但是,当我调整框架大小时,JLabel不会resize。 我没有向North,S,E等添加任何组件。 我希望只是简单地让标签内的图像填满整个框架,当然我的菜单也是如此。

请原谅我,如果这看起来很傲慢,但我没有别的事情可以继续下去。

我做了一个快速的样本

BorderLayout很宽BorderLayout缩小

看到图像周围的红线,这就是JLabel的边界。 如您所见,标签已经过重新调整以填充整个区域。

这是我用来制作样本的代码

 public class LayoutFrame extends JFrame { public LayoutFrame() throws HeadlessException { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Image image = null; URL url = getClass().getResource("/layout/issue78.jpg"); try { image = ImageIO.read(url); } catch (IOException ex) { ex.printStackTrace(); } JLabel label = new JLabel(new ImageIcon(image)); label.setHorizontalAlignment(JLabel.CENTER); label.setVerticalAlignment(JLabel.CENTER); label.setBorder(new LineBorder(Color.RED, 4)); setLayout(new BorderLayout()); add(label); } public static void main(String[] args) { 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) { } LayoutFrame frame = new LayoutFrame(); frame.setSize(200, 200); frame.setLocationByPlatform(true); frame.setVisible(true); } }); } } 

显然,你需要提供自己的图像;)。

不要忘记,标签不会为您缩放内容,如果这是您的目标,您需要实现自己的组件来实现这一目标。

如果您仍然遇到问题,我建议(在没有进一步证据的情况下)您的标签可能不在您认为的容器中,或者容器布局管理器不是您认为的那样。

UPDATE

我不知道你为什么会遇到组件丢失或菜单问题。 混合重量和重量轻的组件??

菜单栏示例

有菜单栏

在仔细阅读了你的问题后,我设计了一个简单的大小调整图像窗格样本。 为了速度,我依赖于我的库,但实现自己的代码代替我的调用应该相当容易

 public class ImagePane extends JPanel { protected static final Object RESIZE_LOCK = new Object(); private BufferedImage image; private BufferedImage scaledImage; private Timer resizeTimer; public ImagePane() { URL url = getClass().getResource("/layout/issue78.jpg"); try { image = ImageIO.read(url); } catch (IOException ex) { ex.printStackTrace(); } resizeTimer = new Timer(250, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // Simple thread factory to start a slightly lower // priority thread. CoreThreadFactory.getUIInstance().execute(new ResizeTask()); } }); resizeTimer.setCoalesce(true); resizeTimer.setRepeats(false); } @Override public void setBounds(int x, int y, int width, int height) { super.setBounds(x, y, width, height); resizeTimer.restart(); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g; if (scaledImage != null) { // This simply returns a rectangle that takes into consideration //the containers insets Rectangle safeBounds = UIUtilities.getSafeBounds(this); System.out.println("scaledImage = " + scaledImage.getWidth() + "x" + scaledImage.getWidth()); int x = ((safeBounds.width - scaledImage.getWidth()) / 2) + safeBounds.x; int y = ((safeBounds.height - scaledImage.getHeight()) / 2) + safeBounds.y; g2d.drawImage(scaledImage, x, y, this); } } protected class ResizeTask implements Runnable { @Override public void run() { synchronized (RESIZE_LOCK) { if (image != null) { int width = getWidth(); int height = getHeight(); System.out.println("width = " + width); System.out.println("height = " + height); // A simple divide and conquer resize implementation // this will scale the image so that it will fit within // the supplied bounds scaledImage = ImageUtilities.getScaledInstanceToFit(image, new Dimension(width, height), ImageUtilities.RenderQuality.High); System.out.println("scaledImage = " + scaledImage.getWidth() + "x" + scaledImage.getWidth()); repaint(); // this is one of the few thread safe calls } } } } } 

最佳选择是子类ImageIcon并覆盖其paintIcon方法,以使用Graphics.paint(x,y,width,height …)简单地绘制图像。