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

发布于 2024-12-02 19:02:46 字数 747 浏览 0 评论 0原文

在我回到高中之前,我正在创建一个服务器/客户端 MMO 作为暑期项目,我选择在客户端使用 Reddwarf 和 swing。我创建了一个扩展(你猜对了)Canvas 的 GameCanvas 对象,并重写了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 内部,JPanel 除了 GameCanvas 本身之外不包含任何其他内容。

我运行我的程序,我可以看到我当前的时间(以毫秒为单位),最后有一些混乱的数字,整个 JFrame 和所有包含的组件都是灰色的并且有问题。

怎么了?哦,我以前用画布做过很多东西,但从来没有发生过这样的事情。 :/

I'm creating a server/client mmo as a summer project before I head back to high school, and I chose to use Reddwarf and swing for my client side. I created a GameCanvas object that extends (you guessed it) Canvas, and overrode the paint method.

Here is my paint method:

    /**
 * 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 is a two layer bufferstrategy and is pulled from the containing JFrame (which has many many other components)

The GameCanvas is also inside of a JPanel that contains nothing else other than the GameCanvas itself.

I run my program and I can see my current time in millis with some messed up digits towards the end, and the entire JFrame and all containing components are gray and bugged out.

What is happening? O-o I have done a lot of stuff with canvas' before and nothing like this ever happened. :/

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

半寸时光 2024-12-09 19:02:46

如果我必须猜测发生了什么,我会说你在绘制文本之前没有绘制背景。

你说这是一个 Swing 问题,但你却使用了 Canvas。 Swing 默认情况下是双缓冲的,我认为没有理由将 AWT 组件与缓冲策略一起使用。

我以前从未创建过 MMO,但我猜想互联网响应时间将比 Swing 绘画时间慢得多。因此,如果您需要自定义绘画,我建议您只使用 JPanel 并重写 PaintComponent() 方法来进行绘画。不要忘记在开始时调用 super.paintComponent() 。

If I had to guess whats happening I would say you are not painting the background before you paint the text.

You say this is a Swing question and yet you use a Canvas. Swing is double buffered by default and I see no reason to use AWT components with a buffer stategy.

I have never created an MMO before but I would guess that internet response time will be far slower than Swing painting time would ever be. So I would suggest you just use a JPanel if you need custom painting and override the paintComponent() method to do your painting. Don't forget to invoke super.paintComponent() at the start.

我乃一代侩神 2024-12-09 19:02:46

你确实意识到你所做的事情没有任何意义吗?

画布上的绘画中,您将绘制到框架(您的策略),而不是画布。

除了创建它之外,忘记 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();
        }
    }

}

You do realise what you are doing doesn't make any sense?

In the paint on your Canvas you are drawing to your Frame (your strat) and not to the Canvas.

Forget about the BufferStrategy other than creating it, and just paint to your respective components and let JFrame worry about handling the double buffering.

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

I also agree with camickr in that Canvas is not the best thing to paint to, use a JPanel. I know that it doesn't make much sense if you just look at the names of the classes but it does work better that way.

Also it won't repaint unless you give it a reason to repaint. Try, from your game thread, calling myJFrame.repaint();.


Here's an SSCCE that works fine.

This is why an SSCCE is important. I had to make assumptions and when I plumbed your pastebin snippet in to something that ran, there is no problem, so I can not give you constructive advice on how to fix your problem.

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

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文