1

I asked a similar question yesterday however after further research on what I wished to accomplish I have reason to believe that the question answered was inadequate and deserves a new question in itself as the question yesterday would solve a different problem and help others but not my particular problem. Link to previous question here.

What I am trying to accomplish is to set the JFrame's contentPane to the size of 200,200, however after drawing two different rectangles you would notice the obvious difference. Please refer to the SSCCE included and the picture attached.

Simply put, I would like Canvas.getWidth()/getHeight and getContentPane.getWidth()/Height to return my specified size 200,200.

Referenced Picture

Referenced Picture

SSCCE Example

import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;

import javax.swing.JFrame;
import javax.swing.SwingUtilities;

@SuppressWarnings("serial")
public class SSCCE extends Canvas implements Runnable {

    private JFrame frame;
    private BufferStrategy bufferStrategy;
    private Graphics2D graphics;
    private boolean running = false;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {             
                SSCCE game = new SSCCE();
                game.setPreferredSize(new Dimension(200,200));
                game.setFocusable(true);
                game.setIgnoreRepaint(true);
                game.frame = new JFrame("SSCCE");
                game.frame.setLayout(new BorderLayout());
                game.frame.getContentPane().setPreferredSize(new Dimension(200,200));
                game.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                game.frame.add(game, BorderLayout.CENTER);
                game.frame.pack();
                game.frame.setIgnoreRepaint(true);
                game.frame.setResizable(false);
                game.frame.setLocationRelativeTo(null);
                game.frame.setVisible(true);
                game.start();
            }
        });
    }

    public synchronized void start() {
        this.createBufferStrategy(2);
        bufferStrategy = this.getBufferStrategy();
        graphics = (Graphics2D) bufferStrategy.getDrawGraphics();
        Thread thread = new Thread(this, "main");
        thread.start();
        running = true;
    }

    @Override
    public void run() {
        while (running) {
            graphics = (Graphics2D) bufferStrategy.getDrawGraphics(); 
            graphics.setColor(Color.RED);
            graphics.fillRect(0, 0, 210, 210);
            graphics.setColor(Color.GREEN);
            graphics.fillRect(0, 0, 200, 200);
            graphics.setColor(Color.BLACK);
            graphics.drawString("Specified Width: 200", 0, 10);
            graphics.drawString("Specified Height: 200", 0, 20);
            graphics.drawString("Canvas Width: " + getWidth(), 0, 30);
            graphics.drawString("Canvas Height: " + getHeight(), 0, 40);
            graphics.drawString("Content Pane Width: " + frame.getContentPane().getWidth(), 0, 50);
            graphics.drawString("Content Pane Width: " + frame.getContentPane().getHeight(), 0, 60);
            graphics.drawString("Red Rectangle = 210,200", 0, 70);
            graphics.drawString("Green Retangle = 200,200", 0, 80);
            graphics.dispose();
            bufferStrategy.show();
        }
    }
}
Community
  • 1
  • 1
synjunked
  • 35
  • 1
  • 6
  • Do you want the content area to be 200x200 or the frame area to be 200x200 – MadProgrammer Feb 07 '13 at 01:58
  • @madprogrammer I'm on the road so I'm using this account but I'd like the contentpane to be 200,200. Which hopefully will change the canvas width to that dimension as well. Please refer to the code thanks again for yesterday. – synjunked Feb 07 '13 at 02:11
  • After further research it seems I should be adding the canvas via getcontentpane I will try it when I get home and post results – synjunked Feb 07 '13 at 02:51
  • `Canvas` isn't a `Container`...tried that ;) – MadProgrammer Feb 07 '13 at 02:53

1 Answers1

2

The problem, as far as I can deduce (from examples and other posts) is the frame border. Every example I can find will either use a JWindow or a undecorated frame...

enter image description here

Mixing heavy and light weight components is only going to lead to tears, I'd recommend not adding a Canvas directly to the frame.

Swing is also double buffered itself. Unless you have a particular issue, I would suggest trying to simple paint within the normal Swing pipeline...

Updated

Well, I've got some bad news, I'm not sure for who though ;)

I was able to adapt the example from here and get it to work...

enter image description here

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception ex) {
                }

                Canvas canvas = new Canvas();
                canvas.setPreferredSize(new Dimension(200, 200));

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setIgnoreRepaint(true);
                frame.add(canvas);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

                canvas.createBufferStrategy(2);

                Thread t = new Thread(new Painter(canvas));
                t.setDaemon(true);
                t.start();

            }
        });
    }

    public class Painter implements Runnable {

        private Canvas canvas;

        public Painter(Canvas canvas) {
            this.canvas = canvas;
        }

        @Override
        public void run() {
            while (true) {
                BufferStrategy bs = canvas.getBufferStrategy();
                Graphics2D g2d = (Graphics2D) bs.getDrawGraphics();
                g2d.setColor(Color.RED);
                g2d.fillRect(0, 0, canvas.getWidth(), canvas.getHeight());

                int width = canvas.getWidth();
                int height = canvas.getHeight();

                FontMetrics fm = g2d.getFontMetrics();
                g2d.setColor(Color.BLACK);
                g2d.drawString("Size = " + width + "x" + height, 0, fm.getAscent());

                Window w = SwingUtilities.windowForComponent(canvas);
                g2d.drawString("Frame Size = " + w.getWidth() + "x" + w.getHeight(), 0, (fm.getHeight()) + fm.getAscent());

                g2d.dispose();
                bs.show();

                try {
                    Thread.sleep(30);
                } catch (InterruptedException ex) {
                }
            }
        }
    }
}

More Bad News

After playing around with the code a little more, I was finally able to get your example to work. I just had to remove game.frame.setResizable(false); :P

Finally, good news

Call setResizable before you call pack...

Community
  • 1
  • 1
MadProgrammer
  • 323,026
  • 21
  • 204
  • 329
  • I have considered that as well however I have seen numerous posts on the benefits of using canvas over jpanel for games. One such benefit being active rendering vs passive rendering. Could you possibly refute that or have a better solution? The reason why I would need a static width and height would be so I can draw my sprites accordingly. – synjunked Feb 07 '13 at 03:16
  • *"Could you possibly refute that"* - Probably not, but you could take a look at [this](http://stackoverflow.com/questions/12642852/the-images-are-not-loading/12648265#12648265) and [this](http://stackoverflow.com/questions/13540534/how-to-make-line-animation-smoother/13547895#13547895) and [this](http://stackoverflow.com/questions/13022754/java-bouncing-ball/13022788#13022788) as examples of VERY simple animation's using Swing – MadProgrammer Feb 07 '13 at 03:22
  • Yea I've tried setting the decorations to false and that was when I saw the correct changes I suppose adding a jpanel and adding the canvas to that would work – synjunked Feb 07 '13 at 03:37
  • Yikes.... can't have people resizing either.... hmm interesting though would there be an alternative for resizeable(false) – synjunked Feb 07 '13 at 04:02
  • Nothing I've tried seems to be able to resolve the issue. Once I set the frame as unresizable, it adds 10 pixels to the width/height of the canvas... – MadProgrammer Feb 07 '13 at 04:26
  • Thanks for the challenge - now if I can just remember, resize before pack :P – MadProgrammer Feb 07 '13 at 04:38