设置背景时JFrame位置发生变化

时间:2018-10-20 17:29:40

标签: java swing

我正在学习如何在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());

2 个答案:

答案 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()指定组件的最大和最小尺寸。