我正在学习如何在JSwing中使用布局,并且在设置JFRame的背景图像时遇到了一些麻烦。
我正在使用一个自定义类,该类重写paintComponent以使用ImageIcon:
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
public class ImagePanel extends JPanel {
private Image image = null;
public ImagePanel(String filename) {
this.image = new ImageIcon(filename).getImage();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, image.getWidth(null), image.getHeight(null), null);
}
}
这是我的主要课程:
public ClientGUI() throws IOException {
instance = this;
this.setPreferredSize(new Dimension(400, 400));
this.setResizable(false);
this.setTitle("ScanIt");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(new FlowLayout(FlowLayout.CENTER));
ImagePanel panel = new ImagePanel("C:\\barcode_background.jpg");
BoxLayout boxLayout = new BoxLayout(panel, BoxLayout.Y_AXIS);
panel.setLayout(boxLayout);
panel.add(Box.createVerticalStrut(30));
JLabel lblLogo = new JLabel("Scan-It");
lblLogo.setOpaque(true);
lblLogo.setFont(new Font("Tahoma", Font.BOLD, 48));
panel.add(lblLogo);
panel.add(Box.createVerticalStrut(50));
JLabel lblEnter = new JLabel("הכנס ברקוד");
lblEnter.setOpaque(true);
lblEnter.setFont(new Font("Tahoma", Font.BOLD, 24));
panel.add(lblEnter);
textField = new JTextField(20);
panel.add(textField);
JButton btnSearch = new JButton("חפש מוצר");
btnSearch.addActionListener(new SearchButtonListener());
panel.add(btnSearch);
panel.add(Box.createVerticalStrut(30));
JButton btnAdmin = new JButton("הוסף מוצר");
btnAdmin.addActionListener(new AdminButtonListener());
panel.add(btnAdmin);
this.add(panel, BorderLayout.CENTER);
this.pack();
this.setVisible(true);
}
由于某些原因,ImagePanel的大小与JFrame的大小不同(如此处显示:http://prntscr.com/l8d98i)。当我将ImagePanel的大小设置为JFrame的大小时,我的组件都将重新调整大小。为什么?如此处所示:http://prntscr.com/l8d9ka
panel.setPreferredSize(this.getPreferredSize());
答案 0 :(得分:1)
由于某些原因,ImagePanel的大小与JFrame的大小不同
好吧,您不应该设置框架的大小。
所有Swing组件均负责确定其自身的大小。因此,您应该将所有组件添加到框架中,然后使用:
frame.pack();
frame.setVisible( true );
这将调用布局管理器,现在框架的大小将基于组件的首选大小。
因此问题出在您的自定义组件上。您需要实现getPreferredSize()
方法以返回图像的大小。然后框架的pack()方法将正常工作。阅读有关Custom Painting的Swing教程中的部分,以获取更多信息和工作示例。
this.setPreferredSize(new Dimension(400, 400));
您不应手动设置首选尺寸。如上所述,pack()方法将计算首选大小。
panel.setPreferredSize(this.getPreferredSize());
这也不是解决方案。框架包含标题栏和边框,因此面板的大小将不会是框架的大小。同样,让图像尺寸确定帧的首选尺寸。
如果需要将图像设置为特定尺寸,请使用Image.getScaledInstance(...)
缩放图像。
当我将ImagePanel的大小设置为JFrame的大小时,所有组件都将重新调整大小。
实际上,仅JTextField会调整大小。由于某些奇怪的原因,JTextField的“最大高度”是无限的。对于JLabel和JButton,最大高度是首选高度。
如T67所述,BoxLayout会将组件的大小调整到最大大小。虽然,如果您从上面遵循我的建议,则无需担心。当框架可调整大小时,这只会在将来的应用程序中成为问题。
我正在使用一个自定义类,该类重写paintComponent以使用ImageIcon
为什么要创建一个ImageIcon而不使用它?不要仅使用ImageIcon(...)来读取图像。
请改为使用ImageIO.read(...)
读取图像并摆脱ImageIcon。这是读取映像的正确方法,如果找不到映像,则会出现错误消息,这有助于调试。
答案 1 :(得分:0)
当BoxLayout从顶部到底部对组件进行布局时,它将尝试按组件的首选高度调整每个组件的大小。如果布局的垂直空间与首选高度的总和不匹配,则BoxLayout会尝试调整组件的大小以填充该空间。组件会增大或缩小以填充空间,而BoxLayout会遵循每个组件的最小和最大尺寸。容器底部会出现多余的空间。
来源:https://docs.oracle.com/javase/tutorial/uiswing/layout/box.html
您可以使用setMaximumSize()
和setMinimumSize()
指定组件的最大和最小尺寸。