为什么我的图形程序中出现线程异常?

时间:2014-12-31 06:45:45

标签: java multithreading swing user-interface graphics

问题:所以我正在尝试创建一个程序,其中一个球在JFrame上来回反弹(后来这会变得更加沉重,所以我使用的是Canvas)。但是,当我尝试运行代码时,我得到以下错误以及一个空白窗口:(任何帮助都会非常感激)

错误:

  Exception in thread "Thread-1" java.lang.IllegalArgumentException: Width (0) and height (0) cannot be <= 0
    at java.awt.image.DirectColorModel.createCompatibleWritableRaster(DirectColorModel.java:1016)
    at sun.java2d.opengl.CGLGraphicsConfig.createCompatibleImage(CGLGraphicsConfig.java:200)
    at java.awt.GraphicsConfiguration.createCompatibleImage(GraphicsConfiguration.java:178)
    at sun.awt.image.SunVolatileImage.getBackupImage(SunVolatileImage.java:236)
    at sun.awt.image.VolatileSurfaceManager.getBackupSurface(VolatileSurfaceManager.java:263)
    at sun.awt.image.VolatileSurfaceManager.initialize(VolatileSurfaceManager.java:126)
    at sun.awt.image.SunVolatileImage.<init>(SunVolatileImage.java:88)
    at sun.awt.image.SunVolatileImage.<init>(SunVolatileImage.java:98)
    at sun.awt.image.SunVolatileImage.<init>(SunVolatileImage.java:109)
    at sun.java2d.opengl.CGLGraphicsConfig.createBackBufferImage(CGLGraphicsConfig.java:356)
    at sun.lwawt.LWCanvasPeer.createBuffers(LWCanvasPeer.java:62)
    at java.awt.Component$FlipBufferStrategy.createBuffers(Component.java:4016)
    at java.awt.Component$FlipBufferStrategy.<init>(Component.java:3956)
    at java.awt.Component$FlipSubRegionBufferStrategy.<init>(Component.java:4479)
    at java.awt.Component.createBufferStrategy(Component.java:3833)
    at java.awt.Canvas.createBufferStrategy(Canvas.java:194)
    at java.awt.Component.createBufferStrategy(Component.java:3756)
    at java.awt.Canvas.createBufferStrategy(Canvas.java:169)
    at gpractice.Window.render(Window.java:37)
    at gpractice.Window.run(Window.java:54)
    at java.lang.Thread.run(Thread.java:724)

这是我的主要Window类和我的Prisoner类的代码:

窗口类代码

 public class Window extends Canvas implements Runnable{
    static Window game = new Window();
    static Prisoner pris;
    static Cop cop;
    static Boolean running = false;
    private Thread thread;
    public static void main(String[]args){
        JFrame frame = new JFrame("Java Sucks!");
        frame.setVisible(true);
        frame.setLocationRelativeTo(null);
        frame.setSize(600, 500);
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setFocusable(true);
        frame.add(game);
        game.start();
    }
    public void init(){
        cop = new Cop();
        pris = new Prisoner();
    }
    public void render(){
        BufferStrategy bs = this.getBufferStrategy();
        if (bs == null)
        {
            createBufferStrategy(3);
            return;
        } 
        Graphics g = bs.getDrawGraphics();
        Graphics2D g2d = (Graphics2D) g;
        g2d.setColor(Color.BLACK);
        //Background///////////////
        g2d.fillRect(0, 0, 600, 500);
        ///////////////////////////
        pris.render(g);
        g.dispose();
        bs.show();

}
    public void run() {
        init();
        while (running){
        render();
        }
        stop();
    }
    private synchronized void start() {
        if (running){
            return;
        }
        else{
            running = true;
        }
            thread = new Thread(this);
            thread.start();
    }
    private void stop() {
        if (!running){
            return;
        }
        else{
            running = false;
        }
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.exit(0);

    }
}

囚犯类代码

public class Prisoner {
    private int x = 0;
    private int y = 0;
    private int dx, dy=0;
    Cop cop = new Cop();

    public  Prisoner(){
        x = 250;
        y = 200;
        dx = 1;
        dy = 1;
    }
    public void render(Graphics g){

        Graphics2D g2d = (Graphics2D) g;
        g2d.setColor(Color.RED);
        g2d.fillOval(x,y,50,50);
        move();
    }
    public void move(){

        if (x <= 0){
            dx = 1;
        }
        if (y <= 0){
            dy = 1; 
        }
        if (x >= 550){
            dx = -1; 
        }
        if (y >=430){
            dy = -1;
        }
        x += dx;
        y += dy;
    }

}

来自Cop类的代码(将来会使用,所以不多)

public class Cop {
private int x;
private int y; 
public Cop()
{
    x = 0;
    y=  0;
}
public void render(Graphics g)
{
    Graphics2D g2d = (Graphics2D) g;
    g2d.setColor(Color.BLUE);
    g2d.fillOval(x, y, 50, 50);
}
}

1 个答案:

答案 0 :(得分:3)

在“开始”游戏之前,请确保窗口已正确实现(连接到本地对等方)并且大小合适。

您还应该确保在Event Dispatching Thread

的上下文中创建UI
public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                ex.printStackTrace();
            }

            JFrame frame = new JFrame("Java Sucks!");
            frame.setResizable(false);
            frame.add(game);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setFocusable(true);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
            frame.addWindowListener(new WindowAdapter() {

                @Override
                public void windowOpened(WindowEvent e) {
                    game.start();
                }
            });

        }
    });
}

因为框架还包括框架装饰,可视区域可能比物理窗口大小小,而不是依赖于幻数,您应该从组件本身获取值

利用getPreferredSize为窗口的布局管理员提供一些想要组件的大小,并JFrame#pack打包内容窗口...

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

public void render() {
    BufferStrategy bs = this.getBufferStrategy();
    if (bs == null) {
        createBufferStrategy(3);
        return;
    }
    Graphics g = bs.getDrawGraphics();
    Graphics2D g2d = (Graphics2D) g;
    g2d.setColor(Color.BLACK);
    //Background///////////////
    g2d.fillRect(0, 0, getWidth(),getHeight());
    ///////////////////////////
    pris.render(g);
    g.dispose();
    bs.show();

}

此外,删除static声明,它们确实很危险并且随着代码复杂性的增加而变得有问题,而不是在static main内创建UI,使用其他一些非静态驱动程序初始化UI

public class MyAwesomeGame {

    public static void main() {
        new MyAwesomeGame()
    }

    public MyAwesomeGame() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                Window game = new Window();
                JFrame frame = new JFrame("Java Sucks!");
                frame.setResizable(false);
                frame.add(game);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setFocusable(true);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
                frame.addWindowListener(new WindowAdapter() {

                    @Override
                    public void windowOpened(WindowEvent e) {
                            game.start();
                    }
                });

            }
        });
    }

}