Java JButtons“扩展”出我的JFrame

Java JButtons“扩展”出我的JFrame,java,swing,jframe,jbutton,Java,Swing,Jframe,Jbutton,对不起,我的英语,我对编程一无所知,因为我是新手,我对按钮和JFrame有问题,请帮助我 我将发布问题的打印,以及我的代码,到目前为止,我有两个类,游戏和菜单,希望你们能解决它,我希望按钮画在灰色面板内 谢谢 打印我的问题 菜单类 package br.com.lexo.dagame.menu; import java.awt.Canvas; import java.awt.Graphics; import java.awt.GridBagLayout; import javax.swi

对不起,我的英语,我对编程一无所知,因为我是新手,我对按钮和JFrame有问题,请帮助我

我将发布问题的打印,以及我的代码,到目前为止,我有两个类,游戏和菜单,希望你们能解决它,我希望按钮画在灰色面板内

谢谢

打印我的问题

菜单类

package br.com.lexo.dagame.menu;

import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.GridBagLayout;

import javax.swing.JButton;
import javax.swing.JFrame;

import br.com.lexo.dagame.Game;

public class Menu extends Canvas {

    private static final long serialVersionUID = 1L;

    public boolean inMenu = false;

    JButton startGame = new JButton("Começar Jogo");
    JButton exitGame = new JButton("Sair do Jogo");
    JButton howToPlay = new JButton("Como Jogar");

    private Game game;

    public Menu(JFrame janela, Game game){

        this.inMenu = true;
        this.game = game;

        game.janela.setLayout(new GridBagLayout());
        game.janela.add(startGame);
        game.janela.add(exitGame);
        game.janela.add(howToPlay);

        howToPlay.setEnabled(false);

    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);

    }

}

我不知道您试图实现什么,但您没有正确添加组件:

看看:

game.janela.setLayout(new GridBagLayout());
game.janela.add(startGame);
game.janela.add(exitGame);
game.janela.add(howToPlay);
这是不正确的,该方法有两个参数,如下所示:container.addcomponent,constraints;您的错误是没有指定约束。约束包含所有详细信息,以了解要在面板中的何处添加该构件

对于每个对象,对象约束都是不同的。对于,约束是GridBagConstraints对象

但是GridBagLayout是最难使用的布局,您并不真正需要它。我建议你看看这个,选择一个布局,并正确地学习它。每个LayoutManager的教程解释了需要在“约束”参数中添加哪些内容

call container.addcomponent的存在是因为有时LayoutManager不需要额外的信息,例如,在其他情况下,它只使用正在使用的LayoutManager的默认约束,这可能不是您所需要的

例如,主菜单中的行:

game.janela.add(game);
是正确的,但它实际做的是调用game.janela.addgame,defaultConstraints;其中defaultConstraints是JFrame janela的LayoutManager的默认约束值。因为您没有明确指定框架的布局,所以它使用JFrames:的默认布局,而BorderLayout的默认约束是常量BorderLayout.CENTER

所以这条线的实际作用是:

game.janela.add(game, BorderLayout.CENTER);
顺便说一句,这正是你想要做的

总结如下:


大多数要添加的调用必须有两个参数:组件和约束。每个LayoutManager使用不同的约束。您必须了解不为LayoutManager指定约束的含义。不要开始学习如何在GridBagLayout中正确使用LayoutManger,因为它要复杂得多。

一种将组件绘制到图形对象的快速方法是调用组件类的绘制方法。因此,在渲染方法中:

g.fillRect(0, 0, getWidth(), getHeight());
menu.startGame.paint(g);
...
但正如你很快就会看到的,所有的东西都画在左上角,就像在另一个答案中所说的,组件的布局,让所有的东西都按照你想要的方式工作是有点复杂

下面的建议是基于我有限的知识,并且很快就组合起来了,所以可能有更好的方法

关于菜单类: 您正在扩展java.awt.Canvas,而我认为最好按照您的需要扩展javax.swing.JPanel这样的容器,我假设保留这3个按钮

下一步是为该应用程序设置适当的布局,该布局将为null。因此,不是:

game.janela.setLayout(new GridBagLayout());
现在是:

setLayout(null);
这是因为您希望在另一个组件(扩展画布的游戏类)上绘制这些按钮的组件,null允许您这样做

因为布局现在是空的,所以必须指定组件的边界,即x和y坐标以及宽度和高度,否则所有内容都将是0、0、0、0,并且不会显示任何内容

所以在游戏的构造器中

setBounds(0, 0, width * scale, height * scale);
janela.Setpreferredsizeze;而不是设置PreferredSizeSize

回到菜单类,您必须设置按钮的边界,如下所示:

Dimensions sgSize = startGame.getPreferredSize();
startGame.setBounds(50, 50, sgSize.width, sgSize.height);
我使用首选大小来获得按钮UI中设置的按钮的最佳宽度和高度

并将它们添加到菜单(现在是JPanel)中,而不是添加到JFramejanela中。addstartGame;另外,别忘了将游戏添加到菜单面板

它应该是这样工作的:

形象


或者,您可以制作自己的小部件工具包或自定义布局,但我不建议这样做。去年我也遇到了同样的问题,但最终还是转到了OpenGL,但无论如何,我希望这能有所帮助:

谢谢您的回答DSquare!这真的很有帮助,我会看看布局管理器并了解更多,谢谢@梅菲很高兴我能帮忙。记住,每当你在StackOverflow得到一个问题的解答时,要投票选出任何有用的答案,并接受最好的答案。您的代码中还有其他一些小问题,例如您没有在main中调用invokeLater,请看。你为什么要这么做是个问题。嗯,嗯,好吧,我会查一查,我不能提高投票率,因为我没有足够的声誉,但我把它作为最好的答案,谢谢!!建议使用空布局时被否决。空布局的第一行是:虽然可以不使用布局管理器,但应该使用布局管理器
呃如果可能的话。它的存在只是因为技术能够实现它,并且需要它来实现LayoutManager,但不应该使用它。我确实说过,我提供的方法可能是,也很可能不是最好的方法,但从某种意义上说,它是一种有效的方法。我尝试过其他解决方案,比如JLayeredPane,但是闪烁太多或者渲染不正确。他的问题只是对如何使用LayoutManager的错误理解,并不复杂。对于这种GUI,他正在尝试做一些非常简单的布局管理器工作得非常好。JLayeredPane根本不相关。此外,不应按照在的paint方法中指定的方式从应用程序调用paint,如果您需要它,并且设计良好的代码不可用,则可以调用repaint。感谢您的评论,我认为我确实从被问到的问题中有点偏离了轨道,这就是我提出JLayeredPane的原因。当然没有问题,我很高兴讨论所有这些,并分享知识。我只是想避免@memphy被搞糊涂或者养成坏习惯,因为这是他的线索。
Dimensions sgSize = startGame.getPreferredSize();
startGame.setBounds(50, 50, sgSize.width, sgSize.height);