Java中的Canvas无法随窗口大小调整?

3

我有一个带有画布的jFrame。在Windows XP/Vista中运行程序并调整窗口大小时,画布会与窗口成比例地调整大小。

然而,在Ubuntu Linux中,当我编译同样的Java应用程序并调整窗口大小时,画布保持相同的大小。

我需要怎么做才能使我的画布在Windows和Linux中随着窗口一起调整大小?这种差异是什么原因导致的?

Main.java

public class Main {
    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));

        BallCanvas ballCanvas = new BallCanvas();

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

BallCanvas.java

public class BallCavnas extends Canvas {
    public BallCanvas()
    {
        setPreferredSize(new Dimension(640, 400));
        setIgnoreRepaint(true);

        ... various gui controls are wired up here
    }
    ... rest of canvas code
}

编辑:我的源代码已经被压缩在这里,如果有人想看一下:
http://www.filedropper.com/ballbounce

我已经按照Dave Ray的建议进行了更改,但Canvas仍然不能调整大小?请记住,当我编译并在Windows上运行此java程序时,它可以正常调整大小。只有在Linux中才会出现这种情况。我正在运行Java 6 Sun 1.6.0.10 JVM,如果有用的话。

alt text http://img158.imageshack.us/img158/7642/screenshotww0.png

也许我的Canvas正在调整大小,但BufferStrategy/Graphics没有调整大小?

编辑2:从屏幕截图来看,它明确设置为CENTER:

frame.getContentPane().add(ballCanvas, BorderLayout.CENTER);
frame.getContentPane().add(controlPanel, BorderLayout.SOUTH);

已解决

显然“Canvas”正在被调整大小,但我在处理其缓冲策略方面做了一些奇怪的事情,这不允许它被调整大小。我已经修复了它。谢谢大家!


Simucal:我以为你只是用来关闭问题,而不是提问的;-)顺便说一下,这是个有趣的问题 :) - OscarRyz
@Oscar Reyes,我是否关闭了你的一个问题或其他什么东西?哈哈。我坐在#Stackoverflow IRC频道里,获取实时的问题流。如果我看到重复的问题,我会尽力识别它...这真是一件麻烦的事情。有时候回忆起之前看过的所有问题/线程可能很困难。 - anon
不是的,但我猜他们决定添加“委员会”关闭功能是为了你。你总是在周围。实际上,一开始只有3个人,但由于你总是占一个位置,现在需要4个人。 :) :) - OscarRyz
@Oscar Reyes,哈哈。关闭问题和编辑问题以使它们具有更好的语法/布局(特别是对于非英语为母语的人)是我在该网站上做出的两个重要贡献。我想人们不喜欢他们的重复问题被关闭,但我只是为了SO的利益而这样做。 - anon
我知道已经过了一段时间,但是你还记得需要做什么来解决这个问题吗? - compman
显示剩余3条评论
4个回答

3
也许布局管理器只是试图遵守您的首选大小。
我建议:
A)删除首选项,看看会发生什么(这不是一个很好的主意)
或者
B)首先不使用画布而是使用JComponent。毕竟Canvas是AWT组件,我不确定它们今天如何工作。JComponent是轻量级组件,因此,如果您将JComponent用作容器,则它们会更好地协同工作。
哎呀..我现在正在提供巫术编程建议。最好开始工作了。
C)对我来说一直有效的方法。通过逐步添加我的代码中的内容来制作小型概念验证。从空画布开始,然后添加首选大小,然后等等。机会是,错误在于绘画方法:P
祝你好运。
:)

2

使用边框布局:

frame.getContentPane().setLayout(new BorderLayout());
BallCanvas ballCanvas = new BallCanvas();
frame.getContentPane().add(ballCanvas, BorderLayout.CENTER);            
frame.getContentPane().add(controlPanel, BorderLayout.SOUTH);

另外,请使用frame.setSize()代替setPreferredSize()来设置显示窗口的初始大小。

你有其他的建议吗?我已经将它改为了BorderLayout,但是画布在调整大小后仍然保留其原始大小。另外,请检查我的编辑。 - mmcdole
@Simucal:你确定把ballCanvas放在了中心位置吗? - Lawrence Dol
@SoftwareMonkey,是的,请看我的编辑。我的代码确实将画布定位在BorderLayout.CENTER。 - mmcdole

2
另一个好的解决方案是将画布放入JPanel中,就像我所做的那样。
    panel.add(new JPanel() {

        @Override
        public void paint(Graphics g) {
          // do not paint
        }

    }.add(capture));

在canvas函数中,类似以下内容:
@Override
public void paint(Graphics g) {
    Dimension currentSize = getParent().getSize();
    int width = currentSize.width;
    int height = currentSize.height;
    if (offscreenImage == null || !currentSize.equals(offscreenDimension)) {
        // call the 'java.awt.Component.createImage(...)' method to get an
        // image
        offscreenImage = createImage(width, height);
        offscreenGraphics = offscreenImage.getGraphics();
        offscreenDimension = currentSize;
    }

    if (image != null) {
        offscreenGraphics.drawImage(image, 0, 0, width, height, null);
    } else {
        offscreenGraphics.setColor(Color.BLACK);
        offscreenGraphics.fillRect(0, 0, width, height);
    }
    //scratch image
    g.drawImage(offscreenImage, 0, 0, this);
}

例如,这使得它非常简单。使用父级面板来适应您的需求。

1
如果你遵循了Dave的建议,尤其是将ballCanvas放在中心位置,那么你必须为ballCanvas设置最大尺寸。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接