为什么我的draw方法只在某些时候起作用?

rqcrx0a6  于 2021-07-13  发布在  Java
关注(0)|答案(2)|浏览(411)

我知道在swing中你应该使用重绘来重绘面板,但是我开始制作游戏,并且已经读到重绘在时间上是不可靠的。所以我试着制定一个策略,创建一个bufferedimage,把我需要的所有东西都画到这个objects图形对象上,然后用drawimage方法把这个图像画到我的jpanel上。
我打电话给dispose让面板重新渲染,但它只是工作的一部分时间。下面只是一个例子。如果你继续运行这个程序,BuffereImage只会被绘制3/10次。有人能给我解释一下吗?

public class TestMain {

public static void main(String[] args) throws InterruptedException {

    JFrame jf = new JFrame();
    MyPanel mp = new MyPanel();
    jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jf.setLocation(50, 500);
    jf.add(mp);
    jf.pack();
    jf.setVisible(true);

    mp.draw();
}
}

public class MyPanel extends JPanel {

private static final long serialVersionUID = 1L;

BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d;

public MyPanel() {
    super();
    setPreferredSize(new Dimension(300, 300));
}

public void draw() {
    System.out.println("In draw");
    g2d = (Graphics2D) img.getGraphics();
    g2d.drawString("Test", 10, 10);

    Graphics g = getGraphics();

    g.drawImage(img, 0, 0, this);
    g.dispose();
}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    System.out.println("In paintComponent");
}

}

在幕后,我在和什么抗争,而这些往往阻碍了抽签。我意识到,调整窗口大小等将调用重绘和覆盖我的绘图,但当我不这样做,它应该显示每次,不是吗?
编辑:有趣。。。如果我把draw方法 Package 成一个连续的while循环,它就会“工作”。但这不能回答我的问题。我不需要经常回忆这个方法来给人一种画画正常的错觉。

xj3cbfub

xj3cbfub1#

不应使用getgraphics()方法进行绘制。使用getgraphics所做的任何代码都只是临时的,每当swing确定组件需要重新绘制时,这些代码都将丢失,这很可能发生在这里。
重写类的getpreferredsize()方法并调用super.paintcomponent(),然后添加system.out.println(…)语句。另外,将system.out.println(…)语句添加到draw()方法以查看代码的执行顺序。
我打电话给dispose让面板重新渲染,
这不会导致面板渲染,它只是释放分配给图形对象的资源。您需要调用draw()方法来不断地重新绘制。
这与使用计时器不断地重新绘制()组件基本相同。不同之处在于draw()可能会立即发生,但重新绘制可能需要几毫秒的时间。但是由于repaint()每次间隔保持不变都需要几毫秒的时间,因此repaint不会只绘制一次,下次再等待一秒钟。

z4bn682m

z4bn682m2#

我修复了您的代码并获得了以下gui:

在缓冲图像上绘制时,您必须执行所有操作。你必须画背景和前景。
在jpanel的paintcomponent方法中绘制缓冲图像时,所要做的就是绘制图像。
swing paintcomponent方法在java版本6、7和8中足够快,可以在不闪烁的情况下进行绘制。我做过动画片,上万行没有闪烁。
必须通过调用swingutilities invokelater方法在事件调度线程上启动swing应用程序。
这是你修改过的代码。

package com.ggl.testing;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class TestMain implements Runnable {

    @Override
    public void run() {
        JFrame jf = new JFrame();
        MyPanel mp = new MyPanel();
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.setLocation(50, 50);
        jf.add(mp);
        jf.pack();
        jf.setVisible(true);
        mp.draw();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new TestMain());
    }

    public class MyPanel extends JPanel {

        private static final long serialVersionUID = 1L;

        BufferedImage img = new BufferedImage(100, 100,
                BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d;

        public MyPanel() {
            super();
            setPreferredSize(new Dimension(300, 300));
        }

        public void draw() {
            System.out.println("In draw");
            g2d = (Graphics2D) img.getGraphics();
            g2d.setColor(Color.WHITE);
            g2d.fillRect(0, 0, img.getWidth(), img.getHeight());
            g2d.setColor(Color.BLACK);
            g2d.drawString("Test", 30, 50);
            g2d.dispose();
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            System.out.println("In paintComponent");
            g.drawImage(img, 0, 0, this);
        }

    }

}

相关问题