Can';t在java中绘制形状

Can';t在java中绘制形状,java,swing,animation,graphics,jframe,Java,Swing,Animation,Graphics,Jframe,我很确定这段代码应该在文本旁边的屏幕上画一个椭圆形。然而,这个词是所有出现的,其余的屏幕是黑色的。这似乎发生在任何原始形状上。我想我对java相当了解,但图形化的东西让我很困惑。我对此束手无策,任何帮助都将不胜感激 import javax.swing.*; import java.awt.*; import java.awt.image.*; import java.util.ArrayList; public class Game extends JPanel implements Run

我很确定这段代码应该在文本旁边的屏幕上画一个椭圆形。然而,这个词是所有出现的,其余的屏幕是黑色的。这似乎发生在任何原始形状上。我想我对java相当了解,但图形化的东西让我很困惑。我对此束手无策,任何帮助都将不胜感激

import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.util.ArrayList;

public class Game extends JPanel implements Runnable {
    int W = 4;
    int H = 3;
    int windowSize = 300;
    boolean running;
    static boolean drawHitBoxes = true;
    int FPSLimit = 30;

    private Thread thread;
    private BufferedImage buffer;
    private Graphics2D g;

    public Game() {
        super();
        setPreferredSize(new Dimension(W * windowSize, H * windowSize));
        setFocusable(true);
        requestFocus();
    }

    public void addNotify() {
        super.addNotify();
        if (thread == null) {
            thread = new Thread(this);
            thread.start();
        }
    }

    public void run() {
        running = true;

        buffer = new BufferedImage(W * windowSize, H * windowSize,
                BufferedImage.TYPE_INT_RGB);
        g = (Graphics2D) buffer.getGraphics();

        // citList.add(new Citizen(200, 200, "Joe"));

        long startTime;
        long waitTime;

        long frameTime = 1000 / FPSLimit; // /How long one frame should take
        long currentFrameTime;

        while (running) {
            startTime = System.nanoTime(); // record when loop starts

            gameUpdate();
            gameRender();
            gameDraw();

            // Calculate how long the current frame took
            currentFrameTime = (System.nanoTime() - startTime) / 1000000;
            waitTime = frameTime - currentFrameTime;

            try {
                Thread.sleep(waitTime);
            } catch (Exception e) {
            } // Sleep for the remaining time
        }
    }

    private void gameUpdate() {
        // for(Citizen i:citList){i.update();} //Update citizens
    }

    private void gameRender() {
        g.setColor(Color.WHITE);
        g.drawOval(100, 100, W - 100, H - 100);
        g.setColor(Color.WHITE);
        g.drawString("Text.", 100, 100);
        System.out.println("Drawing white box.");

        // for(Citizen i:citList){i.draw(g);} //Draw citizens
    }

    private void gameDraw() {
        Graphics gMain = this.getGraphics();
        gMain.drawImage(buffer, 0, 0, null);
    }
}
W是4,H是3,所以既然
W-100
是-96,
H-100
是-97,那么第三个和第四个参数都是负数,这对于
Graphics#drawOval(…)
方法没有意义,因为椭圆的宽度和高度怎么可能是负数。解决方案:确保在调用此方法时只使用有意义的正参数。也许你想要的是:

 // but you'll also want to avoid magic numbers such as 100 & 200 as well
 g.drawOval(100, 100, W * windowSize - 200, H * windowSize - 200);

顺便说一句,我自己更喜欢使用被动图形,在paintComponent中绘制,每当我看到带有图形或Graphics2D实例字段的Swing代码时,我都会感到害怕。。另外,您的代码似乎不遵守Swing线程规则,因为它似乎正在对Swing事件线程进行Swing调用。

我认为最好创建paintComponent方法,并将gameRender和gameDraw传输到那里,然后在while循环中用repaint()替换它们的方法调用。下面是有效的代码

import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.util.ArrayList;

public class Game extends JPanel implements Runnable {
    int W = 4;
    int H = 3;
    int windowSize = 300;
    boolean running;
    static boolean drawHitBoxes = true;
    int FPSLimit = 30;

    private Thread thread;
    private BufferedImage buffer;
    private Graphics2D g;

    public Game() {
        super();
        setPreferredSize(new Dimension(W * windowSize, H * windowSize));
        setFocusable(true);
        requestFocus();
    }

    public void addNotify() {
        super.addNotify();
        if (thread == null) {
            thread = new Thread(this);
            thread.start();
        }
    }

    public void run() {
        running = true;

        buffer = new BufferedImage(W * windowSize, H * windowSize,
                BufferedImage.TYPE_INT_RGB);
        g = (Graphics2D) buffer.getGraphics();

        // citList.add(new Citizen(200, 200, "Joe"));

        long startTime;
        long waitTime;

        long frameTime = 1000 / FPSLimit; // /How long one frame should take
        long currentFrameTime;

        while (running) {
            startTime = System.nanoTime(); // record when loop starts

            gameUpdate();
            //gameRender();
            //gameDraw();
            repaint();

            // Calculate how long the current frame took
            currentFrameTime = (System.nanoTime() - startTime) / 1000000;
            waitTime = frameTime - currentFrameTime;

            try {
                Thread.sleep(waitTime);
            } catch (Exception e) {
            } // Sleep for the remaining time
        }
    }

    private void gameUpdate() {
        // for(Citizen i:citList){i.update();} //Update citizens
    }

    private void gameRender() {
        g.setColor(Color.WHITE);
        //g.drawOval(100, 100, W - 100, H - 100);
        g.drawOval(100, 100, 100, 100);
        g.setColor(Color.WHITE);
        g.drawString("Text.", 100, 100);
        //System.out.println("Drawing white box.");

        // for(Citizen i:citList){i.draw(g);} //Draw citizens
    }

    private void gameDraw(Graphics gMain) {
        //Graphics gMain = this.getGraphics();
        gMain.drawImage(buffer, 0, 0, null);
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        gameRender();
        gameDraw(g);
    }
}

正如@Hovercraft在他的回答中指出的,代码“g.drawOval(100100,W-100,H-100)”中的W-100和H-100将产生负数。我不知道您希望在那里得到什么值,但我只是将它们替换为100以删除错误。

请参见编辑以回答问题。您可能需要:
g.drawOval(100100,W*windowSize-200,H*windowSize-200)updateUI()
,除非您是在更改外观之后调用的。@HovercraftFullOfEels为什么?这会造成延迟吗?@HovercraftFullOfEels。在本例中,触发受保护的void paintComponent(图g)的最佳方法是什么?我更新了答案,并将updateUI()更改为repaint(),我更喜欢1+。有关Swing和AWT中
update()
用法的更多信息,请参阅。
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.util.ArrayList;

public class Game extends JPanel implements Runnable {
    int W = 4;
    int H = 3;
    int windowSize = 300;
    boolean running;
    static boolean drawHitBoxes = true;
    int FPSLimit = 30;

    private Thread thread;
    private BufferedImage buffer;
    private Graphics2D g;

    public Game() {
        super();
        setPreferredSize(new Dimension(W * windowSize, H * windowSize));
        setFocusable(true);
        requestFocus();
    }

    public void addNotify() {
        super.addNotify();
        if (thread == null) {
            thread = new Thread(this);
            thread.start();
        }
    }

    public void run() {
        running = true;

        buffer = new BufferedImage(W * windowSize, H * windowSize,
                BufferedImage.TYPE_INT_RGB);
        g = (Graphics2D) buffer.getGraphics();

        // citList.add(new Citizen(200, 200, "Joe"));

        long startTime;
        long waitTime;

        long frameTime = 1000 / FPSLimit; // /How long one frame should take
        long currentFrameTime;

        while (running) {
            startTime = System.nanoTime(); // record when loop starts

            gameUpdate();
            //gameRender();
            //gameDraw();
            repaint();

            // Calculate how long the current frame took
            currentFrameTime = (System.nanoTime() - startTime) / 1000000;
            waitTime = frameTime - currentFrameTime;

            try {
                Thread.sleep(waitTime);
            } catch (Exception e) {
            } // Sleep for the remaining time
        }
    }

    private void gameUpdate() {
        // for(Citizen i:citList){i.update();} //Update citizens
    }

    private void gameRender() {
        g.setColor(Color.WHITE);
        //g.drawOval(100, 100, W - 100, H - 100);
        g.drawOval(100, 100, 100, 100);
        g.setColor(Color.WHITE);
        g.drawString("Text.", 100, 100);
        //System.out.println("Drawing white box.");

        // for(Citizen i:citList){i.draw(g);} //Draw citizens
    }

    private void gameDraw(Graphics gMain) {
        //Graphics gMain = this.getGraphics();
        gMain.drawImage(buffer, 0, 0, null);
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        gameRender();
        gameDraw(g);
    }
}