【问题标题】:New Canvas not visible unless I resise window除非我调整窗口大小,否则新画布不可见
【发布时间】:2014-05-27 13:40:02
【问题描述】:

基本上我正在制作一个蛇游戏,我想在游戏菜单和实际的蛇游戏之间随意切换,所以我有一个变量 int visibleCanvas 和下面的开关。所以基本上我将主菜单可见性设置为 false,并将游戏设置为可见和可聚焦。

但是屏幕变黑并且在我按下“全屏按钮”(Windows)之前它不会绘制实际的游戏,然后它会按我想要的方式显示游戏。

menu 和 SnakeC 以及扩展 Canvas 的类。

switch (visibleCanvas) {
        case 0:
            menu.setBackground(Color.black);
            menu.setVisible(true);
            menu.setFocusable(true);
            menu.setPreferredSize(new Dimension(640, 480));
            break;

        case 1:
            menu.setVisible(false);
            snakeC.setBackground(Color.black);
            snakeC.setPreferredSize(new Dimension(640, 480));
            snakeC.setVisible(true);
            snakeC.setFocusable(true);
            snakeC.requestFocus();
            break;
}

【问题讨论】:

  • 你的代码 sn-p 的语义让我觉得你想研究一下使用 CardLayout

标签: java applet paint repaint visible


【解决方案1】:

您没有重新验证和重新绘制组件层次结构。如果您不这样做,那么您的应用程序窗口将不会直接重绘,而只会在需要时(例如在调整大小后)。

顺便说一下,如果您正在制作游戏,您可能希望使用 BufferStrategy 研究双缓冲,因为它可能有助于防止动画期间的闪烁,并允许您定期重新绘制 Canvas(确保恒定的帧速率以及流畅的动画)。

否则,这段代码演示了一个在单击第一个实例时切换 Canvas 实例的工作示例(您可以将 MouseListener 替换为您自己想要的任何触发器):

public static void main(String[] args) {
    final JFrame frame = new JFrame("Test");
    frame.setLayout(new BorderLayout());
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    final Canvas canvas1 = new Canvas();
    final Canvas canvas2 = new Canvas();
    canvas1.setBackground(Color.RED);
    canvas2.setBackground(Color.BLUE);
    canvas1.addMouseListener(new MouseAdapter() {
        @Override public void mouseClicked(MouseEvent e) {
            frame.remove(canvas1);
            frame.add(canvas2, BorderLayout.CENTER);
            System.out.println("Canvas switched to Canvas2");
            frame.revalidate();
        }
    });

    SwingUtilities.invokeLater(new Runnable() {
        @Override public void run() {
            frame.add(canvas1);
            frame.setSize(640, 480);
            frame.setVisible(true);
        }
    });
}

【讨论】:

  • 我实际上是:/ 这就是我所关心的。我在 SnakeCanvas 的 run 方法中启动一个线程,我要做的第一件事就是重新绘制。
  • 您确定在 SnakeCanvas 可见之后调用 repaint() 方法?
  • 是的。我在运行方法中启动线程及其第一件事: public void run() { repaint(); while(true) { if (!mainMenu) { if (this.direction != Direction.NO_DIRECTION) { move(); } } 重绘();尝试 { Thread.currentThread();线程.sleep(80); } 捕捉(异常 e){ e.printStackTrace(); } } }
  • 我制作了一个可运行的小示例,可以正确切换 Canvas 实例(尽管方式略有不同)。我相信它会做你想做的事。我会把它添加到这个答案中。
  • 我会尝试根据您的更改我的,但我使用的是 Applet 而不是 Frame。但也许你的会有所帮助
猜你喜欢
  • 2023-03-24
  • 1970-01-01
  • 2014-12-03
  • 1970-01-01
  • 1970-01-01
  • 2013-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多