带有背景图像和 JPanel 的 JFrame

JFrame with Background Image and a JPanel

我有以下内容:

public class Frame {

public static void main(String[] args) {

    JFrame frame = new JFrame("Frame Demo");

    Panel panel = new Panel();        

    frame.add(panel);        

    frame.setBounds(250,100,800,500);
    frame.setVisible(true);
}
}

public class Panel extends JPanel {

JButton singlePlayerButton;
JButton multiPlayerButton;

BufferedImage image;

Gui gui;


public Panel() {
    gui = new Gui();
    add(gui);

    try {
        image = ImageIO.read(new File("C:\Users\void\workspace\BattleShips\src\Testumgebung\background\battleship_main.jpg"));

    } catch (IOException e) {
        e.getMessage();
        e.printStackTrace();
    }

}

public void paintComponent(Graphics g) {
    g.drawImage(image, 0, 0, this.getWidth(), this.getHeight(), null);
}


JLabel text;
JPanel mainMenuPanel;


private class Gui extends JPanel {

    public Gui() {

    setVisible(true);
    setSize(500, 300);
    setLayout(null);

    mainMenuPanel = new JPanel();

    mainMenuPanel.setLayout(null);
    mainMenuPanel.setBackground(Color.BLUE);
    mainMenuPanel.setBounds(150, 10, 200, 230);
    add(mainMenuPanel);
    mainMenuPanel.setVisible(true);


    singlePlayerButton = new JButton("Single Player");
    singlePlayerButton.setBounds(100,50 , 150, 40);

    singlePlayerButton.setVisible(true);

    mainMenuPanel.add(singlePlayerButton);

    multiPlayerButton = new JButton("Multi Player");
    multiPlayerButton.setBounds(100, 100, 150, 40);

    multiPlayerButton.setVisible(true);
    mainMenuPanel.add(multiPlayerButton);

    repaint();
}

}
}

我只想要一个带有 BackgroundImage 和按钮(如单人游戏等)的 MainMenu。我是否必须设置 Layout 或者是否可以不设置 Layout。我刚开始使用 GUI,正如您可以从代码中假设的那样。提前致谢...

Do I have to set a Layout or is it possible without one

作为一般经验法则,是的,您应该尽可能使用布局管理器,它会在长期 运行.

中为您节省大量工作

根据您的代码以及我认为您想要执行的操作,我建议您查看:

作为补充建议:

  • 不要使用 null 布局,像素完美布局是现代 ui 设计中的一种错觉。影响组件个体大小的因素太多,none 是您可以控制的。 Swing 旨在与核心的布局管理器一起工作,丢弃这些将导致无穷无尽的问题和问题,您将花费越来越多的时间来尝试纠正
  • 永远不要引用src,程序导出后它将不存在。尽量避免使用绝对路径,因为不同的计算机会将您的程序放置在不同的位置(并非所有 OS 都有驱动器号的概念)。相反,在您的情况下,您应该使用 getClass().getResource("/Testumgebung/background/battleship_main.jpg")
  • 作为一般规则,您应该在执行任何自定义绘画之前致电 super.paintComponent
  • 为了让您的背景显示出来,添加到其中的所有组件都应设为透明 (setOpaque(false)),这样背景才能显示出来。
  • 将您的 类 划分为职责范围。例如 Panel 应该只管理背景图像而不应该管理其他任何东西,这意味着将 Gui 添加到 Panel 作为一个单独的步骤而不是Panels初始化

作为概念示例...

import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Frame {

    public static void main(String[] args) {

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

                Panel background = new Panel();

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

    public static class Panel extends JPanel {

        BufferedImage image;

        public Panel() {
            setLayout(new BorderLayout());
            try {
                image = ImageIO.read(getClass().getResource("/Testumgebung/background/battleship_main.png"));
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

        @Override
        public Dimension getPreferredSize() {
            return image == null ? super.getPreferredSize() : new Dimension(image.getWidth(), image.getHeight());
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawImage(image, 0, 0, this);
        }

    }

    public static class Gui extends JPanel {

        private MainMenuPane mainMenuPane;
        private CardLayout cardLayout;

        public Gui() {

            setOpaque(false);

            setVisible(true);
            cardLayout = new CardLayout();
            setLayout(cardLayout);

            mainMenuPane = new MainMenuPane();
            // Other views

            add(mainMenuPane, "MainMenu");

            cardLayout.show(this, "MainMenu");

        }

    }

    public static class MainMenuPane extends JPanel {

        JButton singlePlayerButton;
        JButton multiPlayerButton;

        JLabel text;

        public MainMenuPane() {

            setLayout(new GridBagLayout());
            setOpaque(false);
            setBackground(Color.BLUE);

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.ipadx = 20;
            gbc.ipady = 20;

            singlePlayerButton = new JButton("Single Player");

            add(singlePlayerButton, gbc);

            multiPlayerButton = new JButton("Multi Player");

            add(multiPlayerButton, gbc);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            // This is faking transparency, so the background color
            // will be see through
            Graphics2D g2d = (Graphics2D) g.create();
            Composite old = g2d.getComposite();
            g2d.setComposite(AlphaComposite.SrcOver.derive(0.5f));
            g2d.fillRect(0, 0, getWidth(), getHeight());
            g2d.setComposite(old);
        }

    }

}