簡體   English   中英

無法在JPanel上繪制矩形

[英]Can't draw rectangles on JPanel

我目前正在嘗試學習有關揮桿繪畫的更多信息,並且正在創建一個小游戲,但似乎被卡住了。 我試圖將幾個矩形(敵人)添加到ArrayList中,然后在paintComponent()方法中繪制它們,但這似乎不起作用。

這是我的敵人班

import utils.RandomUtils;

import java.awt.*;
import java.awt.geom.Rectangle2D;

public class Enemy
{
    double x, y, w, h;
    Shape enemy;

    Toolkit tk = Toolkit.getDefaultToolkit();
    double width = tk.getScreenSize().width;
    double height = tk.getScreenSize().height;

    RandomUtils utils = new RandomUtils();

    public Enemy(int w, int h)
    {
        this.w = w;
        this.h = h;

        enemy = new Rectangle2D.Double(setX(), setY(), w, h);
    }

    private double setX()
    {
        return x = utils.randInt((int) w, (int) width);
    }

    private double setY()
    {
        return y = utils.randInt((int) h, (int) height);
    }

    public Shape getEnemy()
    {
        return enemy;
    }
}

這是我的董事會班

import players.Enemy;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.util.ArrayList;

public class Board extends JPanel
{
    int x, y, speed = 1, height = 25, width = 25;

    public Board()
    {
        addControls();
    }

    public void addControls()
    {
        Action upAction = new AbstractAction()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                y = y - speed;
                repaint();
            }
        };

        getInputMap(WHEN_FOCUSED).put(KeyStroke.getKeyStroke("W"), "Up Action");
        getActionMap().put("Up Action", upAction);

        Action downAction = new AbstractAction()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                y = y + speed;
                repaint();
            }
        };

        getInputMap(WHEN_FOCUSED).put(KeyStroke.getKeyStroke("S"), "Down Action");
        getActionMap().put("Down Action", downAction);

        Action leftAction = new AbstractAction()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                x = x - speed;
                repaint();
            }
        };

        getInputMap(WHEN_FOCUSED).put(KeyStroke.getKeyStroke("A"), "Left Action");
        getActionMap().put("Left Action", leftAction);

        Action rightAction = new AbstractAction()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                x = x + speed;
                repaint();
            }
        };

        getInputMap(WHEN_FOCUSED).put(KeyStroke.getKeyStroke("D"), "Right Action");
        getActionMap().put("Right Action", rightAction);
    }

    boolean enemiesDrawn = false;
    java.util.List<Enemy> enemies = new ArrayList<>();
    java.util.List<Shape> enemyShapes = new ArrayList<>();

    public void setEnemies()
    {
        for(int enemyCount = 0; enemyCount < 15; enemyCount++)
        {
            System.out.println(enemyCount);
            enemies.add(new Enemy(15, 15));
            enemyShapes.add(enemies.get(enemyCount).getEnemy());
        }
    }

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

        Graphics2D g2 = (Graphics2D) g;

        g.setColor(Color.RED);
        g.fillOval(x, y, width, height);

        if(!enemiesDrawn)
        {
            setEnemies();

            g2.setColor(Color.BLUE);
            g2.setBackground(Color.BLUE);

            enemyShapes.forEach(g2::draw);

            enemiesDrawn = true;
        }
    }
}

實用類

import java.util.Random;

public class RandomUtils
{
    public RandomUtils()
    {
    }

    public int randInt(int min, int max)
    {
        Random rand = new Random();
        return rand.nextInt((max - min) + 1) + min;
    }
}

和主班

import javax.swing.*;

public class MainFrame
{
    JFrame mainFrame;

    public MainFrame()
    {
        mainFrame = new JFrame("Game");

        addComponents();

        mainFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        mainFrame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        mainFrame.setLocationRelativeTo(null);
        mainFrame.pack();
        mainFrame.setVisible(true);
    }

    public void addComponents()
    {
        mainFrame.add(new Board());
    }

    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(MainFrame::new);
    }
}

繪制橢圓形(播放器)效果很好,我似乎無法在列表中繪制敵人。 我應該/可以做些什么來解決這個問題?

所以你的主要問題在這里...

if (!enemiesDrawn) {
    setEnemies();

    g2.setColor(Color.BLUE);
    g2.setBackground(Color.BLUE);

    System.out.println("...");
    enemyShapes.forEach(g2::draw);

    enemiesDrawn = true;
}

一旦paintComponent被調用一次,敵人將永遠不會被再次繪制。 paintComponent可能被調用很多次(通常是快速連續調用),每次調用它時,都希望從頭開始重新繪制組件的整個狀態。

查看AWT和Swing中的 繪畫以及執行自定義繪畫 ,以了解有關在Swing中繪畫如何工作的更多詳細信息

觀察 ...

這是沒有意義的...

mainFrame.setExtendedState(JFrame.MAXIMIZED_BOTH);
mainFrame.setLocationRelativeTo(null);
mainFrame.pack();

您正在將框架設置為最大化,但隨后嘗試打包呢? 這可能會在某些系統上引起問題,請提防。

RandomUtils應該創建一個Random實例,因此冒着使Random以相同順序返回相同值的風險。 您可以單身而行

public enum RandomUtils {

    INSTANCE;

    private Random rand = new Random();

    public int randInt(int min, int max) {
        return rand.nextInt((max - min) + 1) + min;
    }
}

Enemy使用Toolkit並不是一個好主意,除了敵人應該對外界幾乎一無所知的事實之外,考慮到您的窗口帶有裝飾物, Toolkit並不是確定實際可見屏幕尺寸的最佳選擇並且桌面上有諸如任務欄之類的東西,這冒着一些敵人會出現在屏幕上的風險

由於程序的工作方式,很難建議一些可以復制輸出的內容。 但基本上,您應該將所需的位置/大小傳遞給Enemy類的構造函數。

您可以使用ComponentListener並監視componentResized方法,該方法首先使其穩定下來,然后可以根據組件的當前大小創建敵人。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM