如何从多个外部类中绘制 JPanel? [英] How do I draw on a JPanel from multiple outside classes?

查看:27
本文介绍了如何从多个外部类中绘制 JPanel?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在制作一款带有主菜单和您实际玩的世界的游戏.

我有一个名为Game的类,它继承自JPanel并实现了RunnableMouseListenerKeyListenerActionListener 接口(仅包含重要部分)

我还有两个类 InWorldHandlerOutWorldHandler 分别用于处理世界内外的机制.

Game 类:

 公共类 Game 扩展 JPanel 实现 Runnable、KeyListener、MouseListener、ActionListener{受保护的 JFrame 框架;private Timer timer = new Timer(25, this);私人世界;私人播放器播放器 = 新播放器();私人布尔抽奖;游戏(世界世界){frame = new JFrame("我的世界 2D");this.world = 世界;player.enterWorld(world, this);}@覆盖protected voidpaintComponent(Graphics g){Graphics2D g2d = (Graphics2D)g;如果(画){g2d.setColor(新颜色(255, 255, 255));g2d.fillRect(0, 0, frame.getWidth(), frame.getHeight());画=假;//这里,应该处理游戏内的机制如果(玩家.在世界()){块块 = player.getLoadedChunk();for(int x = 0; x <16; x++){for(int y = 0; y <16; y++){块块 = chunk.getBlockAt(x, y);BufferedImage 纹理 = block.getTexture();g2d.drawImage(block.getTexture(), x*32, y*32, texture.getWidth()*2, texture.getHeight()*2, null);}}}//这里,应该处理游戏外的机制别的{}}}@覆盖public void actionPerformed(ActionEvent e){this.repaint();画=真;}@覆盖公共无效运行(){画=真;frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);frame.add(this);frame.setMinimumSize(new Dimension(518, 540));frame.setResizable(false);frame.setLocationRelativeTo(null);frame.addKeyListener(this);frame.addMouseListener(this);frame.setFocusable(true);frame.setVisible(true);框架.pack();定时器开始();}}

其他两个类目前都有空的主体.我只是不知道该怎么做.

我希望 InWorldHandler 类在玩家在游戏中时在面板上绘制,而 OutWorldHandler 类在玩家在主菜单中时,两者都被调用Game 类.我该怎么做?

解决方案

与其使用单个 JPanel,不如尝试使用

I am currently making a game with a main menu and a world where you actually play.

I have a class called Game, which inherits from JPanel and implements the Runnable, MouseListener, KeyListener and ActionListener interfaces (only important parts included)

I also have two classes InWorldHandler and OutWorldHandler for handling the mechanics in the world and outside of it respectively.

The Game class:

public class Game extends JPanel implements Runnable, KeyListener, MouseListener, ActionListener
{
    protected JFrame frame;
    private Timer timer = new Timer(25, this);

    private World world;
    private Player player = new Player();

    private boolean draw;

    Game(World world)
    {
        frame = new JFrame("Minecraft 2D");
        this.world = world;
        player.enterWorld(world, this);
    }

    @Override
    protected void paintComponent(Graphics g)
    {
        Graphics2D g2d = (Graphics2D)g;

        if(draw)
        {
            g2d.setColor(new Color(255, 255, 255));
            g2d.fillRect(0, 0, frame.getWidth(), frame.getHeight());

            draw = false;
            //Here, the in-game mechanics should be handled
            if(player.inWorld())
            {
                Chunk chunk = player.getLoadedChunk();
                for(int x = 0; x < 16; x++)
                {
                    for(int y = 0; y < 16; y++)
                    {
                        Block block = chunk.getBlockAt(x, y);
                        BufferedImage texture = block.getTexture();

                        g2d.drawImage(block.getTexture(), x*32, y*32, texture.getWidth()*2, texture.getHeight()*2, null);
                    }
                }
            }
            //Here, the out-game mechanics should be handled
            else
            {

            }
        }
    }

    @Override
    public void actionPerformed(ActionEvent e)
    {
        this.repaint();
        draw = true;
    }

    @Override
    public void run()
    {
        draw = true;

        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.add(this);
        frame.setMinimumSize(new Dimension(518, 540));
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.addKeyListener(this);
        frame.addMouseListener(this);
        frame.setFocusable(true);
        frame.setVisible(true);
        frame.pack();
        timer.start();
    }
}

Both the other classes have empty bodies currently. I just have no idea how to do that.

I want the InWorldHandler class to draw on the panel when the player is in game, and the OutWorldHandler class when the player is in the main menu, both called in the Game class. How do I do that?

解决方案

Instead of having a single JPanel, why don't you try with a CardLayout and switch whether to show the InnerWorld or the OuterWorld according to a flag that determines where in the program you're at.

As you're implementing KeyListener, I think that's for you to be able to move your character, please take a look at the accepted answer on this question: Keylistener not working for JPanel and use KeyBindings instead.

Also avoid the use of setMimimum/Maximum/PreferredSize() and override those methods instead: Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing?

Take this code as an example:

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Game {
    private JFrame frame;
    private JButton button;
    private boolean status;
    private JPanel[] cards;
    private CardLayout cl;
    private JPanel gamePane;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new Game().createAndShowGUI());
    }

    private void createAndShowGUI() {
        frame = new JFrame(getClass().getSimpleName());
        button = new JButton("Switch Worlds");
        status = true; //True = Inner / False = Outer

        cl = new CardLayout();

        gamePane = new JPanel(cl);
        cards = new JPanel[2];

        cards[0] = new InnerWorld();
        cards[1] = new OuterWorld();

        gamePane.add(cards[0], "innerWorld");
        gamePane.add(cards[1], "outerWorld");

        button.addActionListener(e -> {
            status = !status;
            if (status) {
                cl.show(gamePane, "innerWorld");
            } else {
                cl.show(gamePane, "outerWorld");
            }
        });

        frame.add(gamePane);
        frame.add(button, BorderLayout.SOUTH);

        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

@SuppressWarnings("serial")
class InnerWorld extends JPanel {
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D) g;

        g2d.drawString("Inner World", 50, 50);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(200, 200);
    }
}

@SuppressWarnings("serial")
class OuterWorld extends JPanel {
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D) g;

        g2d.drawString("Outer World", 50, 50);
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(200, 200);
    }
}

这篇关于如何从多个外部类中绘制 JPanel?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆