自定义画布对象不自动重绘

时间:2011-09-04 20:07:22

标签: java swing graphics canvas paint

在我回到高中之前,我正在创建一个服务器/客户端mmo作为夏季项目,我选择使用Reddwarf并为我的客户端摇摆。我创建了一个GameCanvas对象,它扩展了(你猜对了)Canvas,并覆盖了paint方法。

这是我的绘画方法:

    /**
 * Base for drawing the map, player, etc.
 */
@Override
public void paint(Graphics graphics) {
    graphics.dispose();
    if(strat == null) {
        return;
    }
    Graphics2D g = (Graphics2D) strat.getDrawGraphics();
    g.drawString(String.valueOf(System.currentTimeMillis()), 200, 200);
    g.dispose();
    strat.show();
}

Strat是一个双层缓冲区策略,是从包含JFrame(其中包含许多其他组件)中提取的

GameCanvas也在一个JPanel中,除了GameCanvas本身之外别无其他任何东西。

我运行我的程序,我可以看到我在millis中的当前时间,最后有一些乱七八糟的数字,整个JFrame和所有包含的组件都是灰色的并且被排除在外。

发生了什么事? O-o之前我用帆布做了很多东西,没有像这样的事情发生过。 :/

2 个答案:

答案 0 :(得分:2)

如果我不得不猜测发生什么事,我会说你在绘制文字之前没有画背景。

你说这是一个Swing问题但是你使用的是Canvas。默认情况下,Swing是双缓冲的,我认为没有理由使用具有缓冲区状态的AWT组件。

我之前从未创建过MMO,但我猜测互联网响应时间将远远超过Swing绘画时间。所以我建议你只需要使用JPanel,如果你需要自定义绘画并覆盖paintComponent()方法来进行绘画。不要忘记在开始时调用super.paintComponent()。

答案 1 :(得分:2)

你确实意识到你在做什么没有任何意义吗?

画布画颜中,您正在绘制框架(您的策略),而不是画布。

忘记创建它之外的BufferStrategy,只需绘制到各自的组件,让JFrame担心处理双缓冲。

/**
 * Base for drawing the map, player, etc.
 */
@Override
public void paint(Graphics graphics) {
    Graphics g = graphics.create();
    g.drawString(String.valueOf(System.currentTimeMillis()), 200, 200);
    g.dispose();
}

我也同意camickr,因为Canvas并不是最好的绘画,使用JPanel。我知道如果只看一下这些类的名称就没那么有意义了,但它确实更好用。

除非你给它一个重新绘制的理由,否则它不会重新绘制。尝试从您的游戏主题中调用myJFrame.repaint();


这是SSCCE,效果很好。

这就是SSCCE很重要的原因。我不得不做出假设,当我将你的pastebin片段连接到运行的东西时,没有问题,所以我不能就如何解决你的问题给你建设性的建议。

import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class DrawFrame extends JFrame {
    DrawPanel drawPanel;
    static boolean running = false;
    public DrawPanel getDrawPanel() { return drawPanel; }

    public DrawFrame() {
        drawPanel = new DrawPanel();
        add(drawPanel);
    }

    public static void main(String[] args) {
        final DrawFrame mainGui = new DrawFrame();
        final DrawPanel drawPanel = mainGui.getDrawPanel();

        Timer timer = new Timer(0, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                mainGui.setSize(300, 200);
                mainGui.setVisible(true);
                mainGui.createBufferStrategy(2);
                running = true;
            }
        });
        timer.setRepeats(false);
        timer.start();

        while (true && (!running || mainGui.isVisible())) {
            drawPanel.repaint();
        }
    }

    public class DrawPanel extends JPanel {

        @Override
        public void paintComponent(Graphics graphics) {
            super.paintComponent(graphics);
            Graphics g = graphics.create();
            g.drawString(String.valueOf(System.currentTimeMillis()), 100, 100);
            g.dispose();
        }
    }

}