java - 重绘不调用绘制

标签 java swing draw java-2d repaint

我试图在 while 循环内使用 repaint 来调用绘图函数。我不太熟悉重绘的具体工作原理。

我对重绘所做的研究表明,它会等待操作完成,然后再调用绘制方法,这可能是问题所在,因为我处于 while 循环中。

但是我也读到我尝试调用重绘的方式也应该有效,所以我现在很困惑。将一些系统输出放入我的代码中,它似乎没有启动我的任何绘图函数。

什么会导致这种情况?下面列出了我的代码。

游戏窗口.java

package Game;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.*;

import Game.Login;


//our window class that will set up the framework of the game
public class GameWindow {
    public static boolean stillLoading = true;
    public static GridBagConstraints gBC = new GridBagConstraints();
    public static JFrame frame = new JFrame();
    private static boolean useFullScreen = false;

    public GameWindow() {



        //Set game Title
        frame.setTitle("Gaian Empires");
        frame.setLayout(new GridBagLayout());

        //set size of the frame
        if(useFullScreen) { // full screen

            // Disable decorations for the frame.
            frame.setUndecorated(true);
            //put frame to full screen.
            frame.setExtendedState(Frame.MAXIMIZED_BOTH);
        } else { // windowed mode
            // set size of the frame
            frame.setSize(1024,768);
            // put frame to center of screen
            frame.setLocationRelativeTo(null);
            // make it so frame can not be resized
            frame.setResizable(false);
        }

        //Exit the application when user closes frame
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // create instance of the framework so that it extends the canvas 
        // class and puts it to frame
        Login.CreateLogin();    
        frame.setVisible(true);
        frame.add(new Framework());




        stillLoading = false;
    }

    public static void main(String[] args) {
        // Use the event dispatch to build UI for safety.
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new GameWindow();
            }
        });
    }
}

游戏.java

package Game;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.geom.Line2D;

import Game.Login;

public class Game {
    public static boolean login = true;
    public static boolean loginDone = false;

    public Game()
    {
        Framework.gameState = Framework.GameState.GAME_CONTENT_LOADING;

        Thread threadForInitGame = new Thread() {
            @Override
            public void run(){
                // Sets variables and objects for the game.
                Initialize();
                // Load game files (images, sounds, ...)
                LoadContent();

                Framework.gameState = Framework.GameState.PLAYING;
            }
        };
        threadForInitGame.start();
    }


    /**
     * Set variables and objects for the game.
     */
    private void Initialize()
    {

    }

    /**
     * Load game files - images, sounds, ...
     */
    private void LoadContent()
    {

    }    


    /**
     * Restart game - reset some variables.
     */
    public void RestartGame()
    {

    }


    /**
     * Update game logic.
     * 
     * @param gameTime gameTime of the game.
     * if the game is using the mouse for something. @param mousePosition current mouse position.
     */
    public void UpdateGame(long gameTime)
    {
        if (GameWindow.stillLoading) {
            return;
        }
        //System.out.println("UPDATE!");
        if (login == true) {
            Login.showLogin();
            login = false;
        }
    }

    /**
     * Draw the game to the screen.
     * 
     * @param g2d Graphics2D
     * @param mousePosition current mouse position.
     */
    public void Draw(Graphics2D g2d, Point mousePosition)
    {
        System.out.println("drawing!"); 
    }
}

canvas.java

package Game;

import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;

import javax.swing.*;

public abstract class Canvas extends JPanel implements KeyListener, MouseListener {

    // Keyboard states - Here are stored states for keyboard keys - is it down or not.
    private static boolean[] keyboardState = new boolean[525];

    // Mouse States - here are the stored mouse states for mouse key being down or not
    private static boolean[] mouseState = new boolean[3];

    private static boolean noMouse = false; // removes mouse pointer from game.

    public Canvas() {
        // use double buffer to draw the screen
        this.setDoubleBuffered(true);
        this.setFocusable(true);
        //this.setBackground(Color.black);

        // If you will draw your own mouse cursor or if you just want that mouse cursor disappear, 
        // insert "true" into if condition and mouse cursor will be removed.
        if (noMouse) {
            BufferedImage blankCursorImg = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
            Cursor blankCursor = Toolkit.getDefaultToolkit().createCustomCursor(blankCursorImg, new Point(0, 0), null);
            this.setCursor(blankCursor);
        }

        // adds keyboard listener to receive events from jpanel
        this.addKeyListener(this);
        // adds mouse listener to receive events from jpanel
        this.addMouseListener(this);
    }

    // This method is Override in Framework.java and is used for drawing to the screen
    public abstract void Draw(Graphics2D g2d);

    // i think this needs @Override but the system won't allow it.  
    public void paintComponenet(Graphics g) {
        System.out.println("painting");
        Graphics2D g2d = (Graphics2D)g;
        super.paintComponent(g2d);
        Draw(g2d);
    }

    // Keyboard
    /**
     * Is keyboard key "key" down?
     * 
     * @param key Number of key for which you want to check the state.
     * @return true if the key is down, false if the key is not down.
     */
    public static boolean keyboardKeyState(int key) {
        return keyboardState[key];
    }

    // Methods of keyboard listener
    @Override
    public void keyPressed(KeyEvent e) {
        keyboardState[e.getKeyCode()] = true;
    }

    @Override
    public void keyReleased(KeyEvent e) {
        keyboardState[e.getKeyCode()] = false;
        keyReleasedFramework(e);
    }

    @Override
    public void keyTyped(KeyEvent e){
    }

    public abstract void keyReleasedFramework(KeyEvent e);
    // Mouse
    /**
     * Is mouse button "button" down?
     * @param button Number of mouse button for which you want to check the state.
     * @return true if the button is down, false if the button is not down.
     */
    public static boolean mouseButtonState(int button)
    {
        return mouseState[button - 1];
    }

    // Sets mouse key status.
    private void mouseKeyStatus(MouseEvent e, boolean status)
    {
        if(e.getButton() == MouseEvent.BUTTON1)
            mouseState[0] = status;
        else if(e.getButton() == MouseEvent.BUTTON2)
            mouseState[1] = status;
        else if(e.getButton() == MouseEvent.BUTTON3)
            mouseState[2] = status;
    }

    // Methods of the mouse listener.
    @Override
    public void mousePressed(MouseEvent e)
    {
        mouseKeyStatus(e, true);
    }

    @Override
    public void mouseReleased(MouseEvent e)
    {
        mouseKeyStatus(e, false);
    }

    @Override
    public void mouseClicked(MouseEvent e) { }

    @Override
    public void mouseEntered(MouseEvent e) { }

    @Override
    public void mouseExited(MouseEvent e) { }
}

框架.java

package Game;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;

public class Framework extends Canvas {

    // frame width and height
    public static int frameWidth;
    public static int frameHeight;

    //time variables
    public static final long secInNanosec = 1000000000L;
    public static final long milisecInNanosec = 1000000L;

    // FPS
    private final int GAME_FPS = 60;

    // pause between update cycles
    private final long GAME_UPDATE_PERIOD = secInNanosec / GAME_FPS;

    // states of game
    public static enum GameState{STARTING, VISUALIZING, GAME_CONTENT_LOADING, MAIN_MENU, OPTIONS, PLAYING, GAMEOVER, DESTROYED}

    // current game state
    public static GameState gameState;

    // game time
    private long gameTime;

    // help calc game time
    private long lastTime = 0;

    // The actual game
    private Game game = new Game();


    public Framework ()
    {
        super();

        gameState = GameState.VISUALIZING;

        //start game in new thread
        Thread gameThread = new Thread() {
            @Override
            public void run(){
                GameLoop();
            }
        };
        gameThread.start();
    }


    /**
     * Set variables and objects.
     */
    private void Initialize()
    {

    }

    /**
     * Load files - images, sounds, ...
     */
    private void LoadContent()
    {

    }


    /**
     * In specific intervals of time (GAME_UPDATE_PERIOD) the game/logic is updated and then the game is drawn on the screen.
     */
    private void GameLoop()
    {
        // wait some time so that we get correct frame/window resolution.
        long visualizingTime = 0, lastVisualizingTime = System.nanoTime();

        // calculate the time for how long we should put threat to sleep to meet FPS.
        long beginTime, timeTaken, timeLeft;

        while(true)
        {
            beginTime = System.nanoTime();

            switch (gameState)
            {
            case PLAYING:                   
                gameTime += System.nanoTime() - lastTime;                    

                game.UpdateGame(gameTime);

                lastTime = System.nanoTime();
                break;
            case GAMEOVER:
                //...
                break;
            case MAIN_MENU:
                //...
                break;
            case OPTIONS:
                //...
                break;
            case GAME_CONTENT_LOADING:
                //...
                break;
            case STARTING:
                // Sets variables and objects.
                Initialize();
                // Load files - images, sounds, ...
                LoadContent();

                // When all things that are called above finished, we change game status to playing or main menu
                gameState = GameState.PLAYING;
                break;
            case VISUALIZING:
                // this.getWidth() method doesn't return the correct value immediately 
                // So we wait one second for the window/frame to be set to its correct size. Just in case we
                // also insert 'this.getWidth() > 1' condition in case when the window/frame size wasn't set in time,
                // so that we get approximately size.
                if(this.getWidth() > 1 && visualizingTime > secInNanosec)
                {
                    frameWidth = this.getWidth();
                    frameHeight = this.getHeight();

                    // When we get size of frame we change status.
                    gameState = GameState.STARTING;
                }
                else
                {
                    visualizingTime += System.nanoTime() - lastVisualizingTime;
                    lastVisualizingTime = System.nanoTime();
                }
                break;
            case DESTROYED:
                break;
            default:
                break;
            }

            // Repaint the screen.
            repaint();

            // calculate the time for how long we should put threat to sleep to meet FPS.
            timeTaken = System.nanoTime() - beginTime;
            timeLeft = (GAME_UPDATE_PERIOD - timeTaken) / milisecInNanosec; // In milliseconds
            // If the time is less than 10 milliseconds, then we will put thread to sleep for 10 millisecond so that some other thread can do some work.
            if (timeLeft < 10) 
                timeLeft = 10; //set a minimum
            try {
                //Provides the necessary delay and also yields control so that other thread can do work.
                Thread.sleep(timeLeft);
            } catch (InterruptedException ex) { }
        }
    }

    /**
     * Draw the game to the screen. It is called through repaint() method in GameLoop() method.
     */
    @Override
    public void Draw(Graphics2D g2d)
    {
        System.out.println("Paint!");
        switch (gameState)
        {
        case PLAYING:
            System.out.println("we are firing draw");
            game.Draw(g2d, mousePosition());
            break;
        case GAMEOVER:
            //...
            break;
        case MAIN_MENU:
            //...
            break;
        case OPTIONS:
            //...
            break;
        case GAME_CONTENT_LOADING:
            //...
            break;
        case DESTROYED:
            break;
        case STARTING:
            break;
        case VISUALIZING:
            break;
        default:
            break;
        }
    }


    /**
     * Starts new game.
     */
    @SuppressWarnings("unused")
    private void newGame()
    {
        // We set gameTime to zero and lastTime to current time for later calculations.
        gameTime = 0;
        lastTime = System.nanoTime();

        game = new Game();
    }

    /**
     *  Restart game - reset game time and call RestartGame() method of game object so that reset some variables.
     */
    @SuppressWarnings("unused")
    private void restartGame()
    {
        // We set gameTime to zero and lastTime to current time for later calculations.
        gameTime = 0;
        lastTime = System.nanoTime();

        game.RestartGame();

        // We change game status so that the game can start.
        gameState = GameState.PLAYING;
    }


    /**
     * Returns the position of the mouse pointer in game frame/window.
     * If mouse position is null than this method return 0,0 coordinate.
     * 
     * @return Point of mouse coordinates.
     */
    private Point mousePosition()
    {
        try
        {
            Point mp = this.getMousePosition();

            if(mp != null)
                return this.getMousePosition();
            else
                return new Point(0, 0);
        }
        catch (Exception e)
        {
            return new Point(0, 0);
        }
    }


    /**
     * This method is called when keyboard key is released.
     * 
     * @param e KeyEvent
     */
    @Override
    public void keyReleasedFramework(KeyEvent e)
    {

    }

    /**
     * This method is called when mouse button is clicked.
     * 
     * @param e MouseEvent
     */
    @Override
    public void mouseClicked(MouseEvent e)
    {

    }
}

最佳答案

这看起来像问题:

// i think this needs @Override but the system won't allow it.  
public void paintComponenet(Graphics g) {

您尝试重写的方法是paintComponent。你有一个错字。

值得关注编译器警告并了解问题所在。 @Override 错误告诉您您正在尝试重写父类(super class)中不存在的方法。

关于java - 重绘不调用绘制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14294872/

相关文章:

java - 使用 while 循环和延迟更新 Swing GUI

c# - 如何在图片框中选择并 move 矩形?

java - Sonarqube 5.2 不喜欢将工作目录作为符号链接(symbolic link)。如何指定工作目录?

java - 精度损失 - Java

java - 如何存储图像并在存储时同时重命名该图像?

java - 使用 Desktop.getDesktop().edit(File file) 编辑文件时跟踪文件状态

java - Image.setIcon(Parameters) 不刷新标签

java - JTable - TableModelEvent 仅更改的值

c++ - 使用 DT_CALCRECT 的 LPD3DXFONT DrawText?

java - 矩形渐变