【问题标题】:settingContentPane not working设置内容窗格不起作用
【发布时间】:2013-02-07 01:44:54
【问题描述】:

我昨天问了一个类似的问题,但是在对我希望完成的工作进行了进一步研究之后,我有理由相信所回答的问题是不充分的,并且本身值得一个新问题,因为昨天的问题将解决不同的问题并帮助他人,但是不是我的特殊问题。链接到上一个问题here

我想要完成的是将 JFrame 的 contentPane 设置为 200,200 的大小,但是在绘制两个不同的矩形后,您会注意到明显的差异。请参考随附的 SSCCE 和附图。

简单地说,我希望Canvas.getWidth()/getHeightgetContentPane.getWidth()/Height 返回我指定的大小200,200

参考图片

SSCCE 示例

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

【问题讨论】:

  • 内容区域是200x200还是框架区域是200x200
  • @madprogrammer 我正在路上,所以我正在使用这个帐户,但我希望内容窗格为 200,200。希望这也会将画布宽度更改为该尺寸。请参考昨天的代码再次感谢。
  • 经过进一步研究,我似乎应该通过 getcontentpane 添加画布,我回家后会尝试并发布结果
  • Canvas 不是Container...试过了 ;)

标签: java swing awt java-2d


【解决方案1】:

据我所知(从示例和其他帖子),问题是框架边框。我能找到的每个示例都将使用JWindow 或未装饰的框架...

混合使用重和轻组件只会导致流泪,我建议不要直接在框架中添加Canvas

Swing 本身也是双缓冲的。除非您有特殊问题,否则我建议您尝试在正常的 Swing 管道中进行简单的绘制...

更新

好吧,我有一些坏消息,但我不确定是谁;)

我能够改编 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) {
                }
            }
        }
    }
}

更多坏消息

在多玩了一些代码之后,我终于可以让您的示例工作了。我只需要删除game.frame.setResizable(false); :P

最后,好消息

在调用 pack 之前,请先致电 setResizable...

【讨论】:

  • 我也考虑过这一点,但是我看到了很多关于使用画布而不是 jpanel 进行游戏的好处的帖子。这样的好处之一是主动渲染与被动渲染。您能反驳这一点或有更好的解决方案吗?我需要静态宽度和高度的原因是我可以相应地绘制我的精灵。
  • “你能反驳吗?” - 可能不会,但你可以看看 thisthisthis 作为非常简单动画的例子使用 Swing
  • 是的,我尝试将装饰设置为 false,那是当我看到正确的更改时,我想添加一个 jpanel 并将画布添加到它会起作用
  • Yikes.... 也不能让人们调整大小.... 嗯,有趣的是,虽然有替代 resizeable(false) 的方法
  • 我尝试过的任何方法似乎都无法解决问题。一旦我将框架设置为不可调整大小,它就会在画布的宽度/高度上增加 10 个像素...
猜你喜欢
  • 2015-12-31
  • 2018-04-12
  • 1970-01-01
  • 2015-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多