创建带有背景图像的表单(JLayeredPane) [英] Create a form with a background Image (JLayeredPane)

查看:148
本文介绍了创建带有背景图像的表单(JLayeredPane)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在努力做点什么我觉得很简单:

I've been struggling to do something I guess pretty simple :

我想用背景图片创建一个表单(JTextField)。为了使表单不覆盖背景图像,我使用的是JLayeredPane。我一直在尝试不同的东西,似乎没有任何作用:出于某种原因,我要么只显示背景,要么只显示JTextField,但不能同时显示两者。我的目标是拥有一个永不改变的背景图像,只需在其上面使用我的按钮/文本字段。

I want to create a form (JTextField) with a background image. In order for the form not to cover the background Image, I'm using a JLayeredPane. I've been trying different stuff, nothing seems to work : for some reason, I'm either displaying only the background, or only the JTextField, but never both. My goal would be to have a background image that never changes, and just use my buttons / textfields on top of it.

package gestion;

import java.awt.*;

import javax.swing.*;

@SuppressWarnings("serial")
public class Main extends JFrame{
JLayeredPane layeredPane;
JPanel board;
JPanel background;


public Main(){
    super("Test");
    background = new JPanel();
    layeredPane = new JLayeredPane();
    board = new JPanel();

    // Creating frame with LayeredPane
    Dimension boardSize = new Dimension(1280, 1024);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setResizable(false);
    this.setSize(boardSize.width, boardSize.height);
    this.setVisible(true);
    this.setLocationRelativeTo(null);

    layeredPane.setPreferredSize( boardSize );
    this.add(layeredPane);


    // Add a background to the Layered Pane
    JLabel picLabel = new JLabel(new ImageIcon("background.jpg"));
    background.add(picLabel);
    background.setPreferredSize(boardSize);
    background.setBounds(0,0,boardSize.width, boardSize.height);
    layeredPane.add(background, JLayeredPane.DEFAULT_LAYER);

    // Add a JTextField
    final JTextField jtf = new JTextField("Default Value");

    Font police = new Font("Arial", Font.BOLD, 14);
    jtf.setFont(police);
    jtf.setPreferredSize(new Dimension(600, 800));
    background.setBounds(0,0,boardSize.width, boardSize.height);
    jtf.setForeground(Color.BLUE);

    board.add(jtf);
    layeredPane.add(board, JLayeredPane.PALETTE_LAYER);

}

public static void main(String[] args)
{
    new Main();
}

}

只有图像似乎出现,并且由于某种原因(我最好的选择是黑魔法)JTextField不在那里。任何想法或帮助将不胜感激!谢谢!

Only the image seems to appear, and for some reason (My best bet is dark magic) the JTextField is not there. Any ideas or help would be greatly appreciated ! Thank you !

推荐答案

任何时候你依赖任何使用 null的东西布局(如 JLayeredPane ),你会遇到问题。

Any time you rely on anything that uses a null layout (like JLayeredPane), you will run into issues.

你应该使用像......这样的东西/ p>

You should use something like...

board.setBounds(new Rectangle(new Point(0, 0), board.getPreferredSize()));
layeredPane.add(board, JLayeredPane.PALETTE_LAYER);

设置板的大小和位置

null 布局中还存在其他问题的椽子,这些问题只会让他们感到非常痛苦并最终浪费的时间比他们节省的时间更长......

There are also a rafter of other issues with null layouts which just make them a complete pain in the code and end up wasting more time than they save...

坦率地说,一个更简单,更实用的解决方案是创建一个可以为你绘制背景图像的自定义组件这样,您可以使用您需要的布局管理器,而不会遇到这些问题。在任何人跳过我之前,使用你可以使用带有 JLayeredPane 的布局管理器,但这会引入更多问题,必须让组件重叠,以便背景层可以作为背景...更多的是一团糟

Frankly, a simpler and more usable solution would be to create a custom component which could paint the background image for you, this way, you can use what ever layout manager(s) you need and not suffer from these issues. Before anyone jumps all over me, use a you "can" use a layout manager with JLayeredPane, but this then introduces more issues with having to get components to overlap so the background layer can act as the background...just more of a mess

此外,在任何人跳过我之前,你可以使用 JLabel 作为后台组件,在其上设置布局管理器并向其添加组件,但 JLabel 不会根据子项计算所需的大小它包含的组件,而是使用图标文本属性。如果您的背景图片足够大,这可能不是问题,但似乎总是等待中断的弱点。

Also, before anyone jumps all over me, you could use a JLabel as the background component, setting a layout manager on it and adding your components to it, but the JLabel doesn't calculate it's required size based on the child components it contains, but instead, uses the icon and text properties. This might not be an issue if your background image is sufficiently big enough, but always seems like a weak point waiting to break.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setLayout(new BorderLayout());
            BackgroundPane bgPane = new BackgroundPane();
            bgPane.setLayout(new GridBagLayout());
            add(bgPane);

            try {
                BufferedImage bg = ImageIO.read(new File("C:\\Users\\shane\\Dropbox\\MegaTokyo\\thumnails\\megatokyo_omnibus_1_3_cover_by_fredrin-d4oupef.jpg"));
                bgPane.setBackgroundImage(bg);
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            JLabel show = new JLabel("Bananas are yellow");
            show.setOpaque(true);
            show.setForeground(Color.RED);
            show.setBackground(Color.YELLOW);
            show.setBorder(new EmptyBorder(20, 20, 20, 20));
            bgPane.add(show);

        }

    }

    public class BackgroundPane extends JPanel {

        private BufferedImage img;

        @Override
        public Dimension getPreferredSize() {
            BufferedImage img = getBackgroundImage();

            Dimension size = super.getPreferredSize();
            if (img != null) {
                size.width = Math.max(size.width, img.getWidth());
                size.height = Math.max(size.height, img.getHeight());
            }

            return size;
        }

        public BufferedImage getBackgroundImage() {
            return img;
        }

        public void setBackgroundImage(BufferedImage value) {
            if (img != value) {
                BufferedImage old = img;
                img = value;
                firePropertyChange("background", old, img);
                revalidate();
                repaint();
            }
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            BufferedImage bg = getBackgroundImage();
            if (bg != null) {
                int x = (getWidth() - bg.getWidth()) / 2;
                int y = (getHeight() - bg.getHeight()) / 2;
                g.drawImage(bg, x, y, this);
            }
        }

    }

}

这个实现缺少自动缩放或重复等功能,但你明白了这个想法

This implementation is missing things like auto scaling or repeating, but you get the idea

这篇关于创建带有背景图像的表单(JLayeredPane)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆