在画布上进行动画的画布和面板渲染时出现问题 [英] Problem with having Canvas and Panel rendering on Frame for animation

查看:73
本文介绍了在画布上进行动画的画布和面板渲染时出现问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用Jpanel画布时遇到问题,需要优化的解决方案
i是从该论坛上的某个帖子中获得了此设计。

i have problem with canvas Jpanel and need optimized solution i got this design from one of the post on this forum.

我有三个类:

一个是用于动画的画布(BallPanel),一个是帧(Main),另一个是用于挥杆控件的面板(ControlPanel)

one is for animation which is canvas(BallPanel), one is frame(Main) and one is panel for swing controls(ControlPanel)

Main正在同时渲染ControlPanel和BallPanel,但最后,我看不到BallPanel的drawworld()渲染,但我只能看到ControlPanel 。

Main is rending both Controlpanel and BallPanel, but in the end, i can't see the drawworld() rendering from BallPanel but i can only ControlPanel.

我看不到动画和黑色背景,好像控制面板全部位于框架上,而画布(黑色背景)则位于该面板的后面/下方或某处但不可见

BallPanel:

BallPanel:

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

        } catch (Exception e) {
            System.out.println("Exception: " + e);
        }
        box = new Box(0, 0, BOX_WIDTH, BOX_HEIGHT);
        setPreferredSize(new Dimension(800, 600));
        setIgnoreRepaint(true);

        // Wire up Events
//      MouseHandler mouseHandler = new MouseHandler();
//      addMouseMotionListener(mouseHandler);
//      addMouseListener(mouseHandler);
    }



public void drawworld() throws RemoteException {

        if (strategy == null || strategy.contentsLost())
        {
            // Create BufferStrategy for rendering/drawing
            this.createBufferStrategy(2);
            strategy = getBufferStrategy();
            Graphics g = strategy.getDrawGraphics();
            this.g2 = (Graphics2D) g;
        }

        // Turn on anti-aliasing
        this.g2.setRenderingHint (RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    //  box.draw(this.g2); // this can be another but it's also not working

        // Render Background
        this.g2.setColor(Color.BLACK);
        this.g2.fillRect(0, 0, getWidth(), getHeight());

        serball = aBall.getState();// other version UNcomment this line

        for (int i = 0; i < currentNumBalls; i++) {
            this.g2.setColor(serball[i].getBallColor(velocity.getLength()));
            this.g2
                    .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()));

        }


public void mainLoop() {

        long previousTime = System.currentTimeMillis();
        long currentTime = previousTime;
        long elapsedTime;
        long totalElapsedTime = 0;
        int frameCount = 0;

        while (true) {
            currentTime = System.currentTimeMillis();
            elapsedTime = (currentTime - previousTime); // elapsed time in
            // seconds
            totalElapsedTime += elapsedTime;
            if (totalElapsedTime > 1000) {
                currentFrameRate = frameCount;
                frameCount = 0;
                totalElapsedTime = 0;
            }


                try {
                    drawworld();
                } catch (RemoteException e1) {
                    e1.printStackTrace();
                }


            try {
                Thread.sleep(5);
            } catch (Exception e) {
                e.printStackTrace();
            }

            previousTime = currentTime;
            frameCount++;

        }
    }


public void start()
    {
        mainLoop();
    }

start()上方的Main类从此处调用:

the Main class above start() is calling from here :

public static void main(String[] args)
    {


                JFrame frame = new JFrame("BallBounce");

                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(),BoxLayout.Y_AXIS));


                BallPanel ballCanvas = new BallPanel();

                ControlPanel controlPanel = new ControlPanel(ballCanvas);

                frame.getContentPane().add(ballCanvas);
                frame.getContentPane().add(controlPanel);
                frame.pack();
                frame.setVisible(true);

                ballCanvas.start();
        }

这是作为控制者工作的controlpanel:

this is controlpanel whichis working as controller:

public class ControlPanel extends JPanel {

    private BallPanel mainPanel;
    private JButton resetButton;

    public ControlPanel(BallPanel mainPanel)
    {
        this.setPreferredSize(new Dimension(200, 60));
        this.setMaximumSize(new Dimension(5000, 100));
        this.mainPanel = mainPanel;

....
..
..
private class ButtonHandler implements ActionListener
    {

        public void actionPerformed(ActionEvent e) 
        {
            JButton source = (JButton)e.getSource();

            if (source == resetButton)
            {
                mainPanel.clearBalls();
            }

非常感谢您的帮助,以及如何使用RMI动画处理GUI交互/控制
可以告诉优化方式的摆动控件。
jibby lala

Many thanks for any help and how we could handle such GUI with RMI animation and swing control for interacting/controlling that can somebody tell optimized way. jibby lala

PS:我以为在调用远程方法并渲染drawworld时出现了一些线程问题,线程正在暂停或阻塞

P.S: i thought there is some thread problem while i m calling the remote method and rendering the drawworld, either of thread is going on suspension or blocked

交叉发布: http://www.coderanch.com/forums/jforum?module=posts&action=edit&post_id=2406332&start=0

我使用计时器制作了这个,但是问题仍然存在,请提供帮助:

i made this with timer but the problems persist please help:

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();// other version UNcomment this line

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

            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);
            }   
        }

请帮助。

推荐答案

在EDT上,当您调用(true)和Thread.sleep(...)时,看起来好像是线程问题。主Swing线程。您是否已阅读 Swing中的并发?如果不是,请查看其中链接的文章。还强烈考虑使用Swing Timer驱动动画而不是while(true)和Thread.sleep(...)。

It looks like a thread issue as it appears to me you're calling while (true) and Thread.sleep(...) on the EDT, the main Swing thread. Have you read up on Concurrency in Swing? If not, check out the article linked to within. Also strongly consider using a Swing Timer to drive your animation instead of while (true) and Thread.sleep(...).

这篇关于在画布上进行动画的画布和面板渲染时出现问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆