如何解决设置菜单的背景图像并调整其大小
所以我正在尝试为我正在开发的游戏制作菜单。
我想将图像作为背景放置在menuPanel
上,但是我不知道每次抬起窗口时如何让图像重新缩放。我做了一个JLabel
,并且从主要方法中导入了一个图像,当我启动游戏时,我可以看到该图像已正确导入,但是我想填满所有menuPanel
并拉伸为我将窗口增大到全屏或减小到我的框架的最小尺寸。
我该怎么办?
如您在屏幕截图中所见,我希望文本位于图像顶部,并且图像作为背景和全屏显示。
public class Window extends Canvas{
private static final long serialVersionUID = 6331412385749386309L;
private static final int WIDTH = 1024,HEIGHT = WIDTH / 16 * 9;
private JFrame frame;
private JPanel mainPanel;
private JPanel menuPanel;
private JPanel buttonsPanel;
private JPanel playPanel;
private JPanel optionsPanel;
private JButton playBtn;
private JButton optionsBtn;
private JButton quitBtn;
private int currWidth = WIDTH,currHeight = HEIGHT;
public Window(String title,Game game) {
frame = new JFrame(title);
frame.setSize(1024,576);
frame.setMinimumSize(new Dimension(WIDTH,HEIGHT));
frame.requestFocus();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(true);
frame.setLocationRelativeTo(null);
menu();
game.start();
}
private void menu() {
frame.getContentPane().setLayout(new BorderLayout(0,0));
mainPanel = new JPanel();
mainPanel.setBackground(new Color(255,255,255));
frame.getContentPane().add(mainPanel);
mainPanel.setLayout(new CardLayout(0,0));
// menuPanel config
menuPanel = new JPanel();
menuPanel.setForeground(new Color(0,0));
menuPanel.setBackground(new Color(0,0));
mainPanel.add(menuPanel,"menuPanel");
buttonsPanel = new JPanel();
buttonsPanel.setBorder(null);
buttonsPanel.setBackground(new Color(0,0));
// playBtn config
playBtn = new JButton("Play");
playBtn.setForeground(new Color(255,255));
playBtn.setFont(new Font("Segoe Script",Font.BOLD,40));
playBtn.setOpaque(false);
playBtn.setContentAreaFilled(false);
playBtn.setBorderPainted(false);
playBtn.setFocusPainted(false);
// optionsBtn config
optionsBtn = new JButton("Options");
optionsBtn.setForeground(new Color(255,255));
optionsBtn.setFont(new Font("Segoe Script",35));
optionsBtn.setOpaque(false);
optionsBtn.setContentAreaFilled(false);
optionsBtn.setBorderPainted(false);
optionsBtn.setFocusPainted(false);
//quitBtn config
quitBtn = new JButton("Quit");
quitBtn.setForeground(new Color(255,255));
quitBtn.setFont(new Font("Segoe Script",35));
quitBtn.setOpaque(false);
quitBtn.setContentAreaFilled(false);
quitBtn.setBorderPainted(false);
quitBtn.setFocusPainted(false);
GroupLayout gl_buttonsPanel = new GroupLayout(buttonsPanel);
gl_buttonsPanel.setHorizontalGroup(
gl_buttonsPanel.createParallelGroup(Alignment.TRAILING)
.addGroup(gl_buttonsPanel.createSequentialGroup()
.addContainerGap()
.addGroup(gl_buttonsPanel.createParallelGroup(Alignment.LEADING)
.addComponent(quitBtn,GroupLayout.DEFAULT_SIZE,175,Short.MAX_VALUE)
.addComponent(playBtn,Short.MAX_VALUE)
.addComponent(optionsBtn,Short.MAX_VALUE))
.addContainerGap())
);
gl_buttonsPanel.setVerticalGroup(
gl_buttonsPanel.createParallelGroup(Alignment.LEADING)
.addGroup(gl_buttonsPanel.createSequentialGroup()
.addContainerGap()
.addComponent(playBtn)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(optionsBtn,GroupLayout.PREFERRED_SIZE,74,GroupLayout.PREFERRED_SIZE)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(quitBtn,71,GroupLayout.PREFERRED_SIZE)
.addContainerGap(GroupLayout.DEFAULT_SIZE,Short.MAX_VALUE))
);
buttonsPanel.setLayout(gl_buttonsPanel);
//
JLabel menuImageLabel = new JLabel(new ImageIcon(Game.menu_image.getScaledInstance(700,400,Image.SCALE_FAST)));
//
GroupLayout gl_menuPanel = new GroupLayout(menuPanel);
gl_menuPanel.setHorizontalGroup(
gl_menuPanel.createParallelGroup(Alignment.TRAILING)
.addGroup(gl_menuPanel.createSequentialGroup()
.addComponent(menuImageLabel,762,GroupLayout.PREFERRED_SIZE)
.addGap(0)
.addComponent(buttonsPanel,195,Short.MAX_VALUE))
);
gl_menuPanel.setVerticalGroup(
gl_menuPanel.createParallelGroup(Alignment.LEADING)
.addGroup(gl_menuPanel.createSequentialGroup()
.addGap(161)
.addComponent(buttonsPanel,Short.MAX_VALUE)
.addGap(124))
.addComponent(menuImageLabel,537,Short.MAX_VALUE)
);
menuPanel.setLayout(gl_menuPanel);
// playPanel config
playPanel = new JPanel();
playPanel.setBackground(new Color(0,255));
mainPanel.add(playPanel,"playPanel");
// optionsPanel config
optionsPanel = new JPanel();
optionsPanel.setBackground(new Color(255,0));
mainPanel.add(optionsPanel,"optionsPanel");
frame.setVisible(true);
setActions();
}
private void setActions() {
// playBtn action
playBtn.addMouseListener(new MouseAdapter() {
public void mouseEntered(MouseEvent e) {
playBtn.setForeground(new Color(200,210,10));
}
public void mouseExited(MouseEvent e) {
playBtn.setForeground(new Color(255,255));
}
public void mouseClicked(MouseEvent e) {
menuPanel.setVisible(false);
playPanel.setVisible(true);
optionsPanel.setVisible(false);
}
});
// optionsBtn action
optionsBtn.addMouseListener(new MouseAdapter() {
public void mouseEntered(MouseEvent e) {
optionsBtn.setForeground(new Color(200,10));
}
public void mouseExited(MouseEvent e) {
optionsBtn.setForeground(new Color(255,255));
}
public void mouseClicked(MouseEvent e) {
menuPanel.setVisible(false);
playPanel.setVisible(false);
optionsPanel.setVisible(true);
}
});
// quitBtn action
quitBtn.addMouseListener(new MouseAdapter() {
public void mouseEntered(MouseEvent e) {
quitBtn.setForeground(new Color(200,10));
}
public void mouseExited(MouseEvent e) {
quitBtn.setForeground(new Color(255,255));
}
public void mouseClicked(MouseEvent e) {
System.exit(0);
}
});
}
public void tick() {
mainPanel.getSize(new Dimension(currWidth,currHeight));
System.out.println(currWidth + "," + currHeight);
}
public void render() {
}
}
解决方法
摇摆基于父子关系。
因此,如果要在背景上显示按钮,则代码的结构必须为:
- frame
- background component
- buttons panel
最简单的方法是将JLabel
用作背景图像。然后将按钮面板添加到标签。唯一的问题是,默认情况下,JLabel
不使用布局管理器,因此您需要查看布局管理器才能达到所需的效果。
我建议使用GridBagLayout
,然后按钮将在面板上居中。基本代码为:
JPanel buttons = new JPanel();
buttons.add(...);
JLabel background = new JLabel(...);
background.setLayout( new GridBagLayout() );
background.add(buttons,new GridBagConstraints());
标签将以背景图片的大小显示。
如果您希望背景图像随着帧大小的变化而缩放,则有两种选择:
- 使用Stretch Icon。它将自动将图像缩放到可用空间。
- 用JPanel替换JLabel并自己绘制图像。检出Background Panel,可以将其配置为自动缩放图像。
编辑:
我试图阅读代码及其真正令人困惑的地方。
好吧,您的意图不是让您阅读代码。目的是让您使用代码。
编程时,您将学习如何使用类以及该类的方法。当您使用ImageIcon
类时,您是先阅读了代码还是只是学习了如何使用其构造函数?
现在我同意,这两个类没有公开的API,但是您实际上只需要了解这些类的构造函数和方法即可使用它们。
如果您阅读Stretch Icon
博客,则其中会指出:
StretchIcon是ImageIcon的直接替代品,它得到了扩展,但不支持ImageIcon的no-arg构造函数。
这意味着如果您通常使用:
JLabel background = new JLabel( new ImageIcon("background.jpg") );
您将对StretchIcon
使用以下内容:
JLabel background = new JLabel( new StretchIcon("background.jpg") );
与BackgroundPanel
类似,如果您阅读该博客,则指出它是:
JPanel的扩展,它为图像的绘制提供了一些自定义的绘画支持
然后继续说,默认设置是绘制“缩放”的图像,这正是您想要的。因此,您需要弄清楚的是要使用哪个构造器来创建面板。
对于常规面板,您将使用:
JPanel background = new JPanel();
对于BackgroundPanel
,最简单的构造函数将是该类的第一个构造函数,该类仅将Image
作为参数:
JPanel background = new BackgroundPanel(image);
现在您有了一个面板,只需在面板上添加3个按钮即可。
我没有编写StretchIcon
类,所以我不知道代码的详细信息,而且只要该类能达到我的期望,我就不会在意这些细节。
我确实写过BackgroundPanel
类,所以如果您有特定问题,那么我可能会为您提供帮助。但是我没有时间去猜测您会感到困惑的代码的哪一部分。
编辑2:
我有3个按钮,我希望它们也位于cemter并伸展,以便它们保持在图像的中心
这是关于学习如何使用布局管理器的信息。我从不使用IDE生成代码。我想完全控制代码。这样可以使代码更整洁,更易于维护。
这使您可以为作业选择适当的布局管理器,并可以轻松地将面板与不同的布局管理器嵌套在一起。在这种情况下,您要使用GridBagLayout,默认情况下,它将在水平和垂直方向上居中添加的任何组件。
默认情况下,BackgroundPanel
使用BorderLayout。但是您可以轻松地更改它以使用GridBagLayout。然后,我将使用带有GridLayout的第二个面板作为按钮。
因此代码将类似于:
JPanel buttonPanel = new JPanel( new GridLayout(0,1,10,0) );
buttonPanel.add(playBtn);
...
backgroundPanel.add(buttonPanel,new GridBagConstraints());
现在,随着边框尺寸的改变,按钮将自动重新居中。
阅读Layout Managers的Swing教程中的部分,以获取更多信息和示例。
随时保留指向Swing教程的链接。它包含大多数Swing基础知识的信息和示例。
,您可以使用JPanel中的方法paintComponent(Graphics g)
和drawImage()
绘制图像。
import java.awt.*;
import java.io.*;
import javax.imageio.ImageIO;
import javax.swing.*;
public class AutoScale extends JFrame{
private Image image;
public AutoScale() {
setTitle("AutoScale");
setResizable(true);
setSize(400,400);
try {
image = ImageIO.read(new File("path to your file"));
}catch(IOException e) {
System.out.println("Image not found");
}
JPanel panelImg = new JPanel() {
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image,30,getWidth()/2,getHeight()/2,null);
}
};
add(panelImg);
}
public static void main(String[] args) {
AutoScale frame = new AutoScale();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
在此示例中,我创建了面板和paintComponent()
。在该方法内,我使用6个参数调用drawImage()
:
- 图片
- x坐标
- y坐标
- 帧的宽度除以2(可以通过添加,减去或除以
的结果来处理图像的大小getWidth()
)
- 框架的高度除以2(与宽度相同)
- imageObserver,通常设置为
null
。
只要Panel的大小发生更改,paintComponent()
方法就会自动被调用,因此不需要像我之前建议的那样使用WindowListener。
注意:我使用try-catch块,因为如果找不到文件,它将引发异常。
希望这很有帮助!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。