睡眠java后图像未绘制 [英] Image not drawing after sleep java

查看:88
本文介绍了睡眠java后图像未绘制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试绘制背景图像,然后在其上绘制字符.在添加睡眠之前,我的代码一直有效,直到我没有获得1500 fps为止.

package sylvyrfysh.screen;

import javax.swing.*;
import java.awt.*;
import game.infos.Information;

public class ImageLoadDraw extends JFrame{
/**
 * 
 */
private static final long serialVersionUID = 1L;
public static void main(){
    DisplayMode dm=new DisplayMode(Information.sX,Information.sY,16,DisplayMode.REFRESH_RATE_UNKNOWN);
    ImageLoadDraw i = new ImageLoadDraw();
    i.run(dm);
}
public void run(DisplayMode dm){
    setBackground(Color.PINK);
    setForeground(Color.WHITE);
    setFont(new Font("Arial",Font.PLAIN,24));
    s=new Screen();
    try{
        loadpics();
        s.setFullScreen(dm,this);
        try{
            Thread.sleep(10000);
        }finally{
            doRun=false;
            s.restoreScreen();
        }
    }catch(Exception e){
        e.printStackTrace();
    }
}
private void loadpics() {
    bg=new ImageIcon("src/sylvyrfysh/screen/maze_icon.png").getImage();
    chara=new ImageIcon("src/sylvyrfysh/screen/char.png").getImage();
    repaint();
}
public void paint(Graphics g){
    if(g instanceof Graphics2D){
        Graphics2D g2=(Graphics2D)g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    }
    while(true&&doRun){
        g.drawImage(bg,0,0,null);
        g.drawImage(bg,0,480,null);
        g.drawImage(bg,360,0,null);
        g.drawImage(bg,360,480,null);
        g.drawImage(bg,720,0,null);
        g.drawImage(bg,720,480,null);
        g.drawImage(chara,imgX,imgY,null);
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
private Screen s;
public static int imgX=0;
private int imgY=525;
private Image bg,chara;
private Boolean doRun=true;
}

关于造成它的原因以及如何解决的任何想法?就像我说的那样,不睡觉就可以了.

解决方案

Swing是一个单线程框架.也就是说,所有UI交互和修改都应在事件调度线程的内容内执行,包括重画请求.

任何停止,阻止或以其他方式阻止此线程运行的操作,都将阻止EDT处理新事件,包括重绘请求.从本质上讲,这将使您的程序似乎已挂起(或停止响应),因为它已经挂起.

在您的run方法中,您正在调用Thread.sleep.这可能会使EDT停止处理新事件,但是由于您实际上已经从主"线程中调用了该方法,因此它实际上可能会起作用,但是...

在您的paint方法中,您有一个无限循环和一个Thread.sleep调用.这些会阻止EDT运行,因为paint是在EDT上下文中调用的.

在某些系统上,绘画不会总是立即发生,直到paint方法返回之前,它可能不会被推送到设备进行输出,因此,即使在paint中循环的想法,无论事实会导致EDT出现问题,无论如何都不是个好主意.

与其他一些UI框架不同,您不需要实现主循环",Swing会为您解决这一问题.

相反,在您的paint方法中,您应该简单地绘制该循环并退出所需要的内容.

相反,您应该做类似...

public void paint(Graphics g){
    // Painting is a complex series of chained methods, failing to call super.paint
    // to cause significant issues
    super.paint(g);
    // Graphics is guaranteed to be an instance of Graphics2D since I think 1.4
    // You should create a copy, so any changes you make are not carried onto the
    // next component, Graphics is shared between all the components being painted
    // in this paint cycle.
    Graphics2D g2=(Graphics2D)g.create();
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    g2.drawImage(bg,0,0,null);
    g2.drawImage(bg,0,480,null);
    g2.drawImage(bg,360,0,null);
    g2.drawImage(bg,360,480,null);
    g2.drawImage(bg,720,0,null);
    g2.drawImage(bg,720,480,null);
    g2.drawImage(chara,imgX,imgY,null);
    // If you create, you should dispose of it...
    g2.dispose();
}

...相反

例如,您应该使用类似javax.swing.Timer的东西来代替Thread.sleep ...

s=new Screen();
try{
    loadpics();
    s.setFullScreen(dm,this);
    Timer timer = new Timer(10000, new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
            s.restoreScreen();
        }
    });
    timer.setRepeats(false);
    timer.start();
}catch(Exception e){
    e.printStackTrace();
}

有关更多详细信息,请参见 Swing中的并发.

>

您还应该避免覆盖顶级容器,尤其是覆盖paint.绘制一系列复杂的链式方法调用,每个方法执行一个特定的工作,并相互叠加以产生最终结果.

相反,您应该从某种自定义组件开始,例如从JPanel扩展,并覆盖它的paintComponent方法,确保在进行任何绘画之前先调用super.paintComponent.

有关更多详细信息,请参见执行自定义绘画

>

I am trying to have a background image draw then have a character draw over it. My code was working until I added sleep do I didn't get 1500 fps.

package sylvyrfysh.screen;

import javax.swing.*;
import java.awt.*;
import game.infos.Information;

public class ImageLoadDraw extends JFrame{
/**
 * 
 */
private static final long serialVersionUID = 1L;
public static void main(){
    DisplayMode dm=new DisplayMode(Information.sX,Information.sY,16,DisplayMode.REFRESH_RATE_UNKNOWN);
    ImageLoadDraw i = new ImageLoadDraw();
    i.run(dm);
}
public void run(DisplayMode dm){
    setBackground(Color.PINK);
    setForeground(Color.WHITE);
    setFont(new Font("Arial",Font.PLAIN,24));
    s=new Screen();
    try{
        loadpics();
        s.setFullScreen(dm,this);
        try{
            Thread.sleep(10000);
        }finally{
            doRun=false;
            s.restoreScreen();
        }
    }catch(Exception e){
        e.printStackTrace();
    }
}
private void loadpics() {
    bg=new ImageIcon("src/sylvyrfysh/screen/maze_icon.png").getImage();
    chara=new ImageIcon("src/sylvyrfysh/screen/char.png").getImage();
    repaint();
}
public void paint(Graphics g){
    if(g instanceof Graphics2D){
        Graphics2D g2=(Graphics2D)g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    }
    while(true&&doRun){
        g.drawImage(bg,0,0,null);
        g.drawImage(bg,0,480,null);
        g.drawImage(bg,360,0,null);
        g.drawImage(bg,360,480,null);
        g.drawImage(bg,720,0,null);
        g.drawImage(bg,720,480,null);
        g.drawImage(chara,imgX,imgY,null);
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
private Screen s;
public static int imgX=0;
private int imgY=525;
private Image bg,chara;
private Boolean doRun=true;
}

Any ideas on what is causing it and how to fix it? Like I said, with no sleep it works fine.

解决方案

Swing is an single threaded framework. That is all UI interactions and modifications are expected to be executed within the content of the Event Dispatching Thread, including repaint requests.

Anything that stops, blocks or otherwise prevents this thread from running will prevent the EDT from processing new events, including repaint requests. This will, essentially, make it appear that you program has hung (or stopped responding), because it has.

In your run method you are calling Thread.sleep. This is likely stopping the EDT from processing new events, but because you've actually called the method from the "main" thread, it might actually work, however...

In you paint method, you have an infinite loop AND a Thread.sleep call. These WILL stop the EDT from running, as paint is called from within the context of the EDT.

Painting won't always occur immediately, on some systems, until the paint method returns, it may not be pushed to the device for output, so, even the idea of looping within the paint, regardless of the fact that it will cause problems for the EDT, is a bad idea any way.

Unlike some other UI frameworks, you do not need to implement a "main-loop", Swing takes care of this for you.

Instead, in your paint method, you should simply paint what you need to paint for that cycle and exit.

Instead, you should do something like...

public void paint(Graphics g){
    // Painting is a complex series of chained methods, failing to call super.paint
    // to cause significant issues
    super.paint(g);
    // Graphics is guaranteed to be an instance of Graphics2D since I think 1.4
    // You should create a copy, so any changes you make are not carried onto the
    // next component, Graphics is shared between all the components being painted
    // in this paint cycle.
    Graphics2D g2=(Graphics2D)g.create();
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

    g2.drawImage(bg,0,0,null);
    g2.drawImage(bg,0,480,null);
    g2.drawImage(bg,360,0,null);
    g2.drawImage(bg,360,480,null);
    g2.drawImage(bg,720,0,null);
    g2.drawImage(bg,720,480,null);
    g2.drawImage(chara,imgX,imgY,null);
    // If you create, you should dispose of it...
    g2.dispose();
}

...instead

Instead of Thread.sleep you should be making use of something like javax.swing.Timer, for example...

s=new Screen();
try{
    loadpics();
    s.setFullScreen(dm,this);
    Timer timer = new Timer(10000, new ActionListener() {
        public void actionPerformed(ActionEvent evt) {
            s.restoreScreen();
        }
    });
    timer.setRepeats(false);
    timer.start();
}catch(Exception e){
    e.printStackTrace();
}

Take a look at Concurrency in Swing for more details.

You should also avoid overriding top level containers and especially overriding paint. Painting a complex series of chained method calls, each one performing a particular job, building up on top of each other to produce a final result.

Instead, you should start with a custom component of some kind, extending from JPanel for example, and override it's paintComponent method, making sure you call super.paintComponent before you do any of you own painting.

Take a look at Performing Custom Painting for more details

这篇关于睡眠java后图像未绘制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆