【问题标题】:JLabel - Cutting Off The Top of ImageJLabel - 切断图像顶部
【发布时间】:2015-01-27 01:36:28
【问题描述】:

在我的新 Java 项目中,我有一个 JFrame,其中有一个带有 BorderLayout 的 JLabel 设置为 North,下面是一个图像。图像非常适合 JFrame,但 JLabel 会切断它的顶部。如何调整此 JLabel 的大小?我试过setPreferredSize,但没有用。帮助将不胜感激。

代码:

    package counter.main;

    import java.awt.BorderLayout;
    import java.awt.Component;
    import java.awt.Dimension;
    import java.awt.FlowLayout;
    import java.awt.Font;
    import java.awt.Image;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.io.IOException;
    import java.net.URL;

    import javax.sound.sampled.AudioInputStream;
    import javax.sound.sampled.AudioSystem;
    import javax.sound.sampled.Clip;
    import javax.sound.sampled.LineUnavailableException;
    import javax.sound.sampled.UnsupportedAudioFileException;
    import javax.swing.ImageIcon;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.SwingConstants;

    public class FoodCounter {

    public static JLabel greet4 = new JLabel("",SwingConstants.CENTER);
    public static JLabel message4 = new JLabel();
    public static JLabel lclicks4  = new JLabel();
    public static JButton buttonClick4 = new JButton("+ Food");
    public static int clicks4 = 0;
    public static URL food =           Main.class.getResource("/counter/main/FoodEating.wav");
    public static JButton back = new JButton("Back");
    public static JLabel bread;

    static JFrame frame = new JFrame("Food Counter"); {
        createView();

        frame.setSize(500, 100);
        frame.setLocationRelativeTo(null);
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.revalidate();
        frame.repaint();
    }

    private void createView() {
        final JPanel panelc = new JPanel();
        frame.getContentPane().add(panelc);

        panelc.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 11));

        greet4.setFont(new Font( "Dialog", Font.PLAIN, 18));
        greet4.setPreferredSize(new Dimension(40, 20));

        panelc.add(message4);

        frame.add(back, BorderLayout.WEST);
        frame.add(greet4, BorderLayout.NORTH);
        back.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                frame.setVisible(false);
                SelectionFrame.frame1.setVisible(true);
            }

        });

        panelc.add(buttonClick4);
        panelc.add(lclicks4);
        updateCounter();

        bread = new JLabel("");
        bread.setPreferredSize(new Dimension(64, 64));
        Image img = new ImageIcon(this.getClass().getResource("/counter/main/SlicedBread64.png")).getImage();
        bread.setIcon(new ImageIcon(img));
        frame.getContentPane().add(bread, BorderLayout.EAST);

        buttonClick4.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                clicks4++;
                updateCounter();
                try {
                AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(food);
                Clip clip = AudioSystem.getClip();
                clip.open(audioInputStream);
                clip.start();
                } catch (IOException | UnsupportedAudioFileException |  LineUnavailableException x) {
                    x.printStackTrace();
                }
                }
            });

        };

    private void updateCounter() {
        lclicks4.setText(clicks4 + "/100 Food  ");

        if (clicks4 < 1) {
            message4.setText("Click to Begin! -->");
        }

        if (clicks4 >= 1 && clicks4 < 10) {
            message4.setText("Keep Going!");
        }

        if (clicks4 >= 10 && clicks4 < 50) {
            message4.setText("Keep 'em Comin'!");
        }

        if (clicks4 >= 50 && clicks4 < 70) {
            message4.setText("Don't Stop!");
        }

        if (clicks4 >= 70 && clicks4 < 80) {
            message4.setText("Almost!");
        }


        if (clicks4 >= 90 && clicks4 < 100) {
            message4.setText("Finish Strong!");
        }

        if (clicks4 >= 100) {
            try {
                Thread.sleep(3000);                 
            } catch(InterruptedException ex) {
                Thread.currentThread().interrupt();
            }
            System.exit(0);
        }
    }       
}

【问题讨论】:

  • 当心setResizable,这会改变框架边框的大小,从而改变内容可用空间的大小。不要使用setSize,而是使用pack,但在将框架设置为不可调整大小后调用它

标签: java swing resize icons jlabel


【解决方案1】:
  • 如果可以避免,请勿在组件和顶级窗口上设置尺寸、首选尺寸或类似问题。
  • 而是通过巧妙地使用布局管理器并在添加所有组件之后调用 setVisible(true) 之前在顶级窗口上调用 pack() 来让 GUI 自行调整大小。
  • 考虑将虚拟文本放入 greet4 JLabel,以便在打包 GUI 时占用空间。一些空间," " 可能就足够了。

不相关的建议:

  • 您的大部分变量应该是instance 变量,而不是static 变量。 Java 是按照面向对象的编程原则构建的,原因有很多,但其中一个主要原因是减少连接及其相关的复杂性。通过使用静态变量和方法,您既可以消除这种好处,也可以避免创建具有高度圈复杂性的程序,从而使调试变得困难。
  • 对于声明为public 的变量也是如此。更喜欢使用 private 字段来帮助减少耦合并增加内聚。
  • 在后台线程中运行长时间运行的代码,例如播放音乐的代码,以避免占用 Swing 事件线程。
  • 切勿在 Swing 事件调度线程或 EDT 中调用 Thread.sleep(...),因为这会使整个 Swing GUI 进入休眠状态。

例如,

import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.*;

@SuppressWarnings("serial")
public class FoodCounter2 extends JPanel {
   public static final String IMAGE_PATH = "https://duke.kenai.com/iconSized/duke.gif";
   private static final Font TITLE_FONT = new Font("Dialog", Font.PLAIN, 18);
   private JLabel titleLabel = new JLabel("Welcome, User", SwingConstants.CENTER);
   private JButton backButton = new JButton("Back");
   private JButton addFoodButton = new JButton("+ Food");
   private JLabel foodCountLabel = new JLabel("0/100 Food");

   public FoodCounter2() throws IOException {
      URL imgUrl = new URL(IMAGE_PATH);
      BufferedImage img = ImageIO.read(imgUrl);
      ImageIcon icon = new ImageIcon(img);

      JPanel foodPanel = new JPanel(new GridBagLayout());
      // JPanel foodPanel = new JPanel();
      GridBagConstraints gbc = new GridBagConstraints();
      gbc.weightx = 1.0;
      gbc.weighty = 1.0;
      gbc.gridx = 0;
      gbc.gridy = 0;
      gbc.insets = new Insets(10, 10, 10, 10);
      foodPanel.add(new JLabel("Click to Begin! --->"), gbc);
      gbc.gridx++;
      foodPanel.add(addFoodButton, gbc);
      gbc.gridx++;
      foodPanel.add(foodCountLabel, gbc);

      JPanel centerPanel = new JPanel(new BorderLayout());
      titleLabel.setFont(TITLE_FONT);
      centerPanel.add(titleLabel, BorderLayout.PAGE_START);
      centerPanel.add(foodPanel, BorderLayout.CENTER);

      setLayout(new BorderLayout());
      add(backButton, BorderLayout.LINE_START);
      add(centerPanel, BorderLayout.CENTER);
      add(new JLabel(icon), BorderLayout.LINE_END);

   }

   private static void createAndShowGui() {
      FoodCounter2 mainPanel  = null;
      try {
         mainPanel = new FoodCounter2();
      } catch (IOException e) {
         e.printStackTrace();
         System.exit(-1);
      }

      JFrame frame = new JFrame("FoodCounter2");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

显示为:

【讨论】:

  • 我尝试使用 pack();在我的 createView 方法结束时,它没有改变。请问还有什么建议吗?另外,我是初学者,我会采纳你的建议。
  • @Graysull:发布您想要的 GUI 和您所看到的图像。如果您的 GUI 设置正确,pack() 方法起作用。
  • 好的,我将尝试使用您所展示的 GridBagLayout。完成后我会报告。
  • @Graysull:我实际上是通过嵌套 JPanel 来使用一堆布局。两个使用BorderLayout,一个,持有图片的中心一个使用GridBagLayout。
  • 我在 foodPanel.add(new JLabel("Click to Begin! ---&gt;"), gbc); 上收到 NullPointerException 错误,尽管我有一个预制的 JLabel。
【解决方案2】:

这是正在发生的事情:

如您所见,面包的顶部被切掉了。这是因为我认为 JPanel 正在覆盖它。

【讨论】: