Java 如何在底部放置我的背景图像
我想把我的背景图像放在这个框架的最底部,按钮放在顶部。但是,我在下面编写的代码不起作用。有人能看到问题在哪里吗 另一件事是,即使我为我的按钮设置了位置,它仍然显示在画面的顶部中心 请忽略注释行。(我只是猜测,希望它们能起作用,但它们显然不起作用。) 问题/解决办法:Java 如何在底部放置我的背景图像,java,swing,frame,layer,Java,Swing,Frame,Layer,我想把我的背景图像放在这个框架的最底部,按钮放在顶部。但是,我在下面编写的代码不起作用。有人能看到问题在哪里吗 另一件事是,即使我为我的按钮设置了位置,它仍然显示在画面的顶部中心 请忽略注释行。(我只是猜测,希望它们能起作用,但它们显然不起作用。) 问题/解决办法: setLocation(…)和setBounds(…)调用类型被大多数布局管理器忽略。使用它们的唯一方法是通过.setLayout(null)将容器的布局设置为null 但是,尽管空布局和setBounds()似乎是让新手们喜欢的
和setLocation(…)
调用类型被大多数布局管理器忽略。使用它们的唯一方法是通过setBounds(…)
.setLayout(null)将容器的布局设置为null代码>
- 但是,尽管空布局和
似乎是让新手们喜欢的创建复杂GUI的最简单和最好的方法,但您创建的Swing GUI越多,在使用它们时遇到的困难就越严重。当GUI调整大小时,它们不会调整您的组件的大小,它们是一个需要增强或维护的皇家女巫,当它们放置在滚动窗格中时会完全失败,当在所有平台或屏幕分辨率与原始分辨率不同的情况下查看时,它们看起来非常糟糕setBounds()
- 总之,不要这样做,不要使用null布局或setBounds,而是嵌套JPanel,每个都使用自己的布局管理器,从而创建易于维护和体面的GUI
- 如果你想在背景中绘制一幅图像,那么就用JPanel的
方法将其绘制到一个JPanel中,作为GUI组件的容器,这在本网站上的许多类似问题中都得到了演示——我马上就会找到我的一些paintComponent(Graphics g)
- 如果在该图像图形JPanel的顶部添加任何JPanel,请确保可以通过在这些重叠的JPanel上调用
来查看它们。否则,您将掩盖图像setOpaque(false)
- 当只需要一个jframe时,代码有两个jframe。把你不用的扔掉
- 在将组件添加到GUI之前,在JFrame上过早调用
——不要这样做。仅在将所有内容添加到GUI后调用它,以便所有内容都显示OKsetVisible(true)
- 您正在创建两个JLayedPanes,并通过将它们添加到JFrame中而完全覆盖其中一个,而不了解JFrame的BorderLayout如何处理添加的组件
- 我建议您甚至不要使用一个JLayeredPane,而是如上所述在JPanel中绘制,并将其用作容器
- 当按下“播放”按钮时,您的代码似乎正在打开一个全新的GUI窗口,如果是这样,用户很快就会感到恼火。考虑交换视图而不是.
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
// extend JPanel so you can draw to its background
@SuppressWarnings("serial")
public class Menu2 extends JPanel {
private BufferedImage bgImage = null; // our background image
private JButton playButton = new JButton(new PlayVsAiAction("Play Vs. AI", KeyEvent.VK_P));
public Menu2(BufferedImage bgImage) {
this.bgImage = bgImage;
setLayout(new GridBagLayout()); // center our button
add(playButton);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (bgImage != null) {
g.drawImage(bgImage, 0, 0, this);
}
}
// to size our GUI to match a constant or the image.
@Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
// if you want to size it based on the image
if (bgImage != null) {
int width = bgImage.getWidth();
int height = bgImage.getHeight();
return new Dimension(width, height);
} else {
return super.getPreferredSize();
}
// if you want to size the GUI with constants:
// return new Dimension(PREF_W, PREF_H);
}
private class PlayVsAiAction extends AbstractAction {
public PlayVsAiAction(String name, int mnemonic) {
super(name); // have our button display this name
putValue(MNEMONIC_KEY, mnemonic); // alt-key to press button
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO code to start program
}
}
private static void createAndShowGui() {
BufferedImage img = null;
String imagePath = "res/img/background.png";
try {
// TODO: fix this -- use class resources to get image, not File
img = ImageIO.read(new File(imagePath));
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
Menu2 mainPanel = new Menu2(img);
JFrame frame = new JFrame("Chinese Chess");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
createAndShowGui();
});
}
}
除了上面的解决方案。。。您应该以以下方式创建和启动swing应用程序:
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
// Instantiate your JFrame and show it
}
谢谢;)@非常感谢!我实际上是java的新手。在你们的两个代码中我都不理解的一行是“SwingUtilities.invokeLater(newrunnable())”。你能告诉我它是做什么用的吗@Jorge@AnthonyZhang考虑到这是一份简短的简历!!!我希望有帮助。使用swing时,对用户界面的任何更新都必须发生在事件调度线程(AWT事件调度线程)上。因此,对任何方法的任何调用都意味着对GUI的更新,应该从这个线程调用。使用invokeLater可以保证代码将在EDT中执行。还有其他选项(如invokeAndWait),但在特定情况下,这将尽快在EDT中执行您的代码(在处理所有其他以前的事件之后),非常感谢!这对解释很有帮助。请给我一些时间修改我的代码,稍后我会给你一些反馈@HoverCraftFullOfeels为什么设置bgImage=null@HovercraftFullOfEels@AnthonyZhang:因为我没有将BuffereImage分配给声明变量的bgImage——我不能,因为这是不可能的。相反,我在构造函数中分配它(您可以清楚地看到)。
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private static void createAndShowGUI() {
// Instantiate your JFrame and show it
}