用画布和计时器绘图

时间:2011-04-02 18:05:11

标签: java swing canvas timer

我有画布的问题我想在画布上显示一些移动的球(动画),但除了黑色背景外我什么都看不到。

有人可以告诉我这段代码中的错误以及它将如何运作。

public CopyOfCleanBallPanel2() throws IOException, InterruptedException {

        frame = new JFrame("simple gaming loop in java");
        frame.setSize(BOX_WIDTH, BOX_WIDTH);
        frame.setResizable(false);

        displayCanvas = new CustomCanvas();
        displayCanvas.setLocation(0, 0);
        displayCanvas.setSize(CANVAS_WIDTH, CANVAS_HEIGHT);
        displayCanvas.setBackground(Color.BLACK);
        displayCanvas.setFont(new Font("Arial", Font.BOLD, 14));
        displayCanvas.setPreferredSize(new Dimension(CANVAS_WIDTH,CANVAS_HEIGHT));

        frame.add(displayCanvas);
        displayCanvas.requestFocus();

        frame.setLocationRelativeTo(null);

        try {
            this.aBall = (BallServer) Naming
                    .lookup("rmi://localhost/BouncingBalls");

        } catch (Exception e) {
            System.out.println("Exception: " + e);
        }


        frame.pack();
        frame.setVisible(true);

        aBall.start();
        startFrameTimer();  
    }

    /*
     * Initializes the frame (also game update) timer.
     */
    private void startFrameTimer() {
        frameTimer.schedule(new FrameTimerTask(), 1, GAME_TIMER_COOLDOWN);
    }

    public void updateSimulation() throws RemoteException {
        repaintCanvas();
    }
    /*
     * This method gets called by the timer. It updates the game simulation and
     * redraws it.
     */
    private void onFrameTimer() throws RemoteException {
        updateSimulation();
    }

    /*
     * Causes the whole canvas to get repainted.
     */
    private final void repaintCanvas() throws RemoteException  {
        Graphics g =  displayCanvas.getGraphics();
        drawworld(g);
    }

    private class FrameTimerTask extends TimerTask {
        public void run() {
            try {
                onFrameTimer();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }
    /*
     * This custom canvas overrides the paint method thus allowing for a custom
     * painting on the component.
     */
    private class CustomCanvas extends Canvas {
        @Override
        public void paint(Graphics g) {
            // Currently the game message gets drawn over the inner border
            // of the canvas so we have to repaint the whole thing.
            try {
                repaintCanvas();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }   
    public void drawworld(Graphics g) throws RemoteException {
            g.setColor(Color.BLACK);
             g.fillRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);

            System.out.println("i m in drawworld ");

            serBall = aBall.getState1(); ***// here it is remote call and there is thread going on suspension*** 

            for (int i = 0; i < currentNumBalls; i++) {
                g.setColor(serBall[i].getBallColor(velocity.getLength()));
                g
                        .fillOval((int) (serBall[i].position.getX() - serBall[i]
                                .getRadius()),
                                (int) (serBall[i].position.getY() - serBall[i]
                                        .getRadius()), (int) (2 * serBall[i]
                                        .getRadius()), (int) (2 * serBall[i]
                                        .getRadius()));

                // Draw our framerate and ball count
                g.setColor(Color.WHITE);
                g.drawString("FPS: " + currentFrameRate + " Balls: "
                        + currentNumBalls, 15, 15);
            }   
        }
P.S:当我调用远程方法并渲染绘图世界时,我认为存在一些线程问题,线程中的任何一个都在暂停或被阻止

请帮助。

jibby lala

2 个答案:

答案 0 :(得分:3)

使用Swing时,自定义绘制是通过覆盖JPanel(或JComponent)的paintComponent()方法完成的,而不是Canvas。 Canvas是一个AWT组件,不应与Swing一起使用。有关更多信息和示例,请参阅Custom Painting上的Swing教程。

应该使用Swing Timer完成动画,以便在EDT上执行代码。 Swing教程还有关于“如何使用Swing Timers”和“Concurrency”的部分,它有助于解释这些概念。

不需要repaintCanvas()方法。要重新绘制组件,只需在组件上调用repaint()即可。你永远不应该使用getGraphics()方法。所有绘制方法都已将Graphics类作为参数接收。这是您应该用于绘画的Grapphics对象。

答案 1 :(得分:2)

看起来好像是mixing heavy and light components,这需要一些小心。或者,您可以将代码与此example进行比较。