简体   繁体   中英

JButtons “extending” out of my JFrame

Sorry about my English, and my ignorance in programming, its because I'm new at this , and I'm having problem with Buttons and JFrame , please help me ;)

I'll post the print of the problem, and the codes of my the two classes I have so far, Game and Menu , hope you guys can solve it, I want the buttons to paint inside the gray panel.

Thanks.

Print of my Problem

在此处输入图片说明 Print

(GAME CLASS)

    package br.com.lexo.dagame;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;

import javax.swing.JFrame;

import br.com.lexo.dagame.menu.Menu;

public class Game extends Canvas implements Runnable {

    private static final long serialVersionUID = 1L;

    private static int width = 300;
    private static int height = width / 16 * 9;
    private static int scale = 3;

    private static String title = "Da Game";

    private Thread thread;
    public JFrame janela;
    private Menu menu;

    private boolean running = false;

    public Game() {

        Dimension size = new Dimension(width * scale, height * scale);
        setPreferredSize(size);

        janela = new JFrame();
        menu = new Menu(janela, this);

    }

    private synchronized void start() {
        if (running) return;
        running = true;
        thread = new Thread(this, "Thread_01");
        thread.start();

    }

    private synchronized void stop() {
        if (!running) return;
        running = false;

        try {
            thread.join();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void render() {

        BufferStrategy bs = getBufferStrategy();

        if (bs == null){
            createBufferStrategy(3);
            return;
        }

        Graphics g = bs.getDrawGraphics();

        g.setColor(Color.LIGHT_GRAY);
        g.fillRect(0, 0, getWidth(), getHeight());
        g.dispose();
        bs.show();

    }

    public void update() {
    }

    public void run() {
        while (running){
            render();
            update();
        }

        stop();

    }

    public static void main(String[] args) {
        Game game = new Game();
        game.janela.add(game);
        game.janela.setTitle(title);
        game.janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        game.janela.pack();
        game.janela.setLocationRelativeTo(null);
        game.janela.setResizable(false);
        game.janela.setVisible(true);

        game.start();
    }

}

(MENU CLASS)

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);

    }

}

I don't know what are you trying to accomplish but you are not adding the components correctly:

Look at:

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

This is incorrect, the add method has two arguments, like this: container.add(component, constraints); your error is not specifying the constraints. The constraints contains all the details to know where in the panel you want to add that component.

For each LayoutManager the Object constraints is diferent. For the GridBagLayout the constraints is a GridBagConstraints object.

However GridBagLayout is a the most difficult layout to use and you don't really need it. I recommend you to look at this visual guide pick a layout and learn it properly. The tutorial for each LayoutManager explains what do you need to put in the constraints parameter.

The call container.add(component) exists because sometimes the LayoutManager does not need extra information (like the BoxLayout ), in the other cases it just uses the "default" constraints for the LayoutManager in use, which may not be what you need.

For example the line in your main:

game.janela.add(game);

Is correct, but what it actually does is calling game.janela.add(game, defaultConstraints); where defaultConstraints is the default constraints value for the LayoutManager of the JFrame janela . Because you didn't explicitely specify a layout for the frame it is using the default layout for JFrames: BorderLayout , and the default constraints for the BorderLayout is the constant BorderLayout.CENTER .

So what that line actually does is:

game.janela.add(game, BorderLayout.CENTER);

Which incidentally is what you wanted to do.

To summarize:

Most calls to add must have two parameters: the component and the constraints. Each LayoutManager uses different constraints. You must be aware of what means to not specify the constraints for your LayoutManager. Do not start learning about how to properly use LayoutMangers with the GridBagLayout it's much more complex.

A quick way to somehow paint components to a graphics object is calling the paint method of component class. So in your render method:

g.fillRect(0, 0, getWidth(), getHeight());
menu.startGame.paint(g);
...

But as you'll soon see that everything is painted on the top left as components are laid out as said in the other answer and to get everything working to how you want them to work is a bit more complicated.

Now the following advice is based on my limited knowledge and was quickly put together so there are probably better ways.

About the menu class: You are extending java.awt.Canvas when I think it would be best to extend a container like javax.swing.JPanel as you want it (I assume) to hold those 3 buttons.

Next would be to set the appropriate layout for this application, which would be null. So instead of:

game.janela.setLayout(new GridBagLayout());

it would now be:

setLayout(null);

This is because you want components (which are those buttons) to be paint on top of another component which is the Game class that extends Canvas and null allows you to do that.

Because the layout is now null, you must specify the bounds of the components which are the x and y coordinates alone with the width and the height otherwise everything will just be 0, 0, 0, 0 and nothing would show up.

So in the Game's constructor

setBounds(0, 0, width * scale, height * scale);

and janela.setPreferredSize(size); instead of setPreferredSize(size);

Back in the Menu class you will have to set the bounds of the buttons like so:

Dimensions sgSize = startGame.getPreferredSize();
startGame.setBounds(50, 50, sgSize.width, sgSize.height);

I am using preferred size to get the optimal width and height of the button that was set in the buttons UI (I think).

and add them to the Menu which is now a JPanel instead of adding them to the JFrame(janela). ( add(startGame); ) Also, don't forget to add the game to the menu panel.

and it should work like so:

( http://i.imgur.com/7cAopvC.png ) (image)

Alternatively you could make your own widget toolkit or custom layout, but I wouldn't recommend that. I had this same problem last year but ended up moving to OpenGL but anyway, I hope this has helped :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM