[Solved] Canvas drawing problem!

Hi guys!
So I’ve been wanting to change the way my menu is going to be initialized and all - basically just remove all swing components, apart from maybe the jframe holding the canvas? :stuck_out_tongue: Anyway, I’ve run into a snag, that is the Graphics2D object won’t draw whatever I want it to draw. I think the problem lies in it only being painted once? - something that shouldn’t matter? Here is the code linked to my problem.


     private void init() {
    	GUI gui = new GUI();
        handler = new InputHandler(gui);
        
	gameFrame = new JFrame("ShootEm UP");
	gameFrame.setLayout(null);
	gameFrame.setPreferredSize(new Dimension(CONST_WIDTH, CONST_HEIGHT));
        gameFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        gameFrame.setResizable(false);
        gameFrame.setIgnoreRepaint(true);
        designMenuBar();
         
        canvas = new Canvas();
        canvas.setBounds(0, 0, CONST_WIDTH, CONST_HEIGHT);
        canvas.setIgnoreRepaint(true);
    	canvas.addMouseMotionListener(handler);
        canvas.addMouseListener(handler);
        canvas.addKeyListener(handler);
        
        
        gameFrame.add(canvas);
        gameFrame.pack();
        
        canvas.createBufferStrategy(2);
        canvas.requestFocus();

        render();
        gameFrame.setVisible(true);
    }

   public void render() {
    	try {
    	BufferStrategy bf = canvas.getBufferStrategy();
        Graphics2D g = (Graphics2D) bf.getDrawGraphics();
        
        test(g);
        
        g.dispose();
        bf.show();
        Toolkit.getDefaultToolkit().sync();
    	}
    	catch (Exception e) {
    		e.printStackTrace();
    	}
    }
    
    private void test(Graphics2D g) {
        g.setColor(Color.GREEN);
        g.drawString("LOL", 100, 100);
        g.fillRect(500, 500, 100, 100);
    }

It’s safe to rule out the gui variable, the handler variable and designMenuBar() function. Anyone got any ideas?

You call BufferStrategy.show() before the window is made visible? Of course it won’t render :stuck_out_tongue:

Also, usually if you will directly control rendering like that, the render()+show() method calls are usually in a loop.

EDIT: And there is no need to call Toolkit.sync() since BufferStrategy takes care of that for you.
EDIT2: canvas.createBufferStrategy(2) is also supposed to throw an IllegalStateException here because you cannot call it before the window is made visible.

I just set the gameFrame.setVisible(true) before the render() call -> still doesn’t draw :(.
For now I actually don’t need it in a loop, I’m using the loop as a running animation*, this is drawn before the loop for animation is called.

About Toolkit.sync() didn’t know that - I’ll keep that in mind! Thanks! :slight_smile:

I ran your code and it does render for me. However, once the window goes out of view or is minimized, the rendering will disappear. Maybe something happens that causes your rendering to disappear. Putting “while(true) render();” at the end of init() should work.

One thing I noticed, calling JFrame.pack() will not cause Canvas.createBufferStrategy(2) to throw an exception. Once I remove it, I do get an exception. Really weird…

You actually made me notice two things here.

  1. The problem is intermittent on windows, I’m dev’ing on a linux box and here it doesn’t show up. Only sometimes - which is a problem since I have no clue how to debug this!. On windows, it successfully renders like 9/10 - but sometimes it fails.

  2. I agree that the problem with the pack is really weird. - I think this may be somehow linked to problem 1, because on windows after many restarts - the menubar seems to pack also - leaving a white bar for the remainder of the canvas (Not really worried about this, since this is what I will be changing, that is more towards games having a centered menu)

In addition, I don’t see why I would need the loop, that is something that really stumps me.

Well you can’t really do anything about either. The thing to learn here is that you can’t render once or else sometimes (or most of the time), something somewhere will cause your screen to want to refresh. Since there is nothing to draw, refreshing will set it to the default light gray background.

I actually fixed it :wink: - what you told me really set me off… was sad.
What triggered the solution?

The packing of the gameFrame.
I was directed here:
http://www.gamedev.net/topic/261754-javalangillegalstateexception-component-must-have-a-valid-peer/

which says I basically can’t create the buffer before it’s displayed (why didn’t I think of that?). Got me to set the visibility of the frame before the canvas created the buffer and i removed the packing. Just set the size of the frame and voila, works like a charm :slight_smile:


    	...
        
        gameFrame.add(canvas);        
        gameFrame.setVisible(true);
        
        canvas.createBufferStrategy(2);
        canvas.requestFocus();

        render();

Interesting…calling JFrame.pack(), then Canvas.createBufferStrategy(2), then JFrame.setVisible(true) still works for me, but doesn’t for you. Oh Swing facepalm

Hey.

createBufferStrategy(…) is an asynchronous operation, that’s why it fails “now and then”. (Sometimes it finishes before the frame is visible, sometimes not).

Try something like


EventQueue.invokeAndWait(new Runnable() {
        public void run() {
            frame.createBufferStrategy(2);
        }
  });

There is no need for that, just call it after the frame is visible, that’s all.

I would set the frame visible, and create the bufferstrategy inside the EventQueue.invokeAndWait() to avoid deadlocks on older java versions, and to make sure that on your first render loop, getBufferStrategy() doesn’t return null.