Java: 只有在类内部访问要呈现的 BufferedImage 才会产生效果

huangapple 未分类评论42阅读模式
英文:

Java: Accessing BufferedImage to be rendered only has an effect inside class

问题

我正在尝试构建一个小型库,以在其他项目中使用,它可以帮助设置一个每秒重绘X次的带有图像的框架。

它由两个类组成:

package displayKit;

public class Runtime 
{
    public Display display;
    static double lastTime;
    static double thisTime;
    public static double deltaT;
    static double lastShortTime;
    public static Thread thread;
    public int FPS = 50;
    public static boolean running = false;
    
    public Runtime(int w, int h)
    {
        display = new Display(w, h);
        lastTime = System.currentTimeMillis();
        lastShortTime = System.currentTimeMillis();
        running = true;
        
        while(running)
        {
            OnUpdate();
        }
    }
    
    void OnUpdate()
    {
        deltaT = (System.currentTimeMillis()-lastShortTime)/1000;
        lastShortTime = System.currentTimeMillis();
        
        while(AssessTime(FPS))
        {
            if(display != null)
            {
                //此处是我放置工作代码的位置
                display.repaint();
            }
        }
    }
    
    public static boolean AssessTime(int FPS)
    {
        ...不相关的代码...
    }
}

以及:

package displayKit;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.Random;

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

public class Display extends JPanel
{
    private static final long serialVersionUID = 1L;
    public static int width;
    public static int height;
    public static Dimension dimension;
    
    public static JFrame frame;
    public static JPanel panel;
    
    public BufferedImage image;
    public Runtime runtime;
    
    public Display(int w, int h)
    {
        width = w;
        height = h;
        dimension = new Dimension(width, height);
        frame = buildJFrame(w, h);
    }
    
    public JFrame buildJFrame(int w, int h)
    {
        JFrame frame = new JFrame();
        frame.setSize(dimension);
        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        panel = this;
        panel.setPreferredSize(dimension);
        panel.setSize(dimension);
        panel.setMaximumSize(dimension);
        panel.setMinimumSize(dimension);
        frame.add(panel);
        frame.setVisible(true);
        frame.pack();
        image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
        return frame;
    }
    
    public void paintComponent(Graphics g)
    {
        g.setColor(Color.black);
        g.fillRect(0, 0, width, height);
        g.drawImage(image, 0, 0, null);
        g.dispose();
    } 
    
    public static BufferedImage ColorNoise(int w, int h)
    {
        ...不相关的代码...
    }
}

我尝试在其他地方(另一个包中)创建Runtime的实例,然后修改Display的变量'image',使得渲染的图像可以在该上下文中以动态且简单的方式进行更改。我有一个生成噪声填充缓冲图像的函数用于测试,当我在OnUpdate()中将Display的'image'设置为这个图像时,它能够工作...

然而,当我尝试在其他地方这样做时,它不起作用,即(伪代码):

public void main(String args[])
{
    Runtime runtime = new Runtime(...)
    while(true)
    {
        runtime.display.image = 随机生成的图像
    }
}

当我将代码放在第一个类中的OnUpdate()中时,它能够工作,并且每帧都会更新为噪声图像,但是当我尝试在其他地方这样做时,不会抛出错误,JFrame保持黑屏。我觉得我的代码结构可能有问题,但我不知道如何使其足够灵活,以便在多个不同的项目中使用。

感谢您的帮助,为我的愚蠢之处道歉!

英文:

I am trying to build a little library, to use on other projects, that helps to set up a frame with an image that is redrawn X times per second.

It consists of two classes:

package displayKit;

public class Runtime 
{
	public Display display;
	static double lastTime;
	static double thisTime;
	public static double deltaT;
	static double lastShortTime;
	public static Thread thread;
	public int FPS = 50;
	public static boolean running = false;
	
	public Runtime(int w, int h)
	{
		display = new Display(w, h);
		lastTime = System.currentTimeMillis();
		lastShortTime = System.currentTimeMillis();
		running = true;
		
		while(running)
		{
			OnUpdate();
		}
	}
	
	void OnUpdate()
	{
		deltaT = (System.currentTimeMillis()-lastShortTime)/1000;
		lastShortTime = System.currentTimeMillis();
		
		while(AssessTime(FPS))
		{
			if(display != null)
			{
                //Where I've been putting the code that works
				display.repaint();
			}
		}
	}
	
	public static boolean AssessTime(int FPS)
	{
		...irrelevant...
	}
}

And:

package displayKit;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.Random;

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

public class Display extends JPanel
{
	private static final long serialVersionUID = 1L;
	public static int width;
	public static int height;
	public static Dimension dimension;
	
	public static JFrame frame;
	public static JPanel panel;
	
	public BufferedImage image;
	public Runtime runtime;
	
	public Display(int w, int h)
	{
		width = w;
		height = h;
		dimension = new Dimension(width, height);
		frame = buildJFrame(w, h);
	}
	
	public JFrame buildJFrame(int w, int h)
	{
		JFrame frame = new JFrame();
		frame.setSize(dimension);
		frame.setResizable(false);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setLocationRelativeTo(null);
		panel = this;
		panel.setPreferredSize(dimension);
		panel.setSize(dimension);
		panel.setMaximumSize(dimension);
		panel.setMinimumSize(dimension);
		frame.add(panel);
		frame.setVisible(true);
		frame.pack();
		image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
		return frame;
	}
	
	public void paintComponent(Graphics g)
	{
		g.setColor(Color.black);
		g.fillRect(0, 0, width, height);
		g.drawImage(image, 0, 0, null);
		g.dispose();
	} 
	
	public static BufferedImage ColorNoise(int w, int h)
    {
        ...irrelevant...
    }
}

I'm trying to create an instance of Runtime elsewhere (in another package) and then modify Display's variable 'image' such that the image rendered may be changed dynamically and simply in that context. I have a function that makes a noise-filled buffered image for testing and when I set Display's 'image' to this in OnUpdate() it works...

However, when I try and do this elsewhere it doesn't work i.e. (pseudocode):

public void main(String args[])
{
    Runtime runtime = new Runtime(...)
    while(true)
    {
        runtime.display.image = (randomly generated image)
    }
}

When I have the code in OnUpdate() as indicated in the first class it works and updates with noise every frame but when I try to do this elsewhere no error is thrown the JFrame just stays black. I feel like I'm structuring my code wrong but I don't know how else to make it flexible enough to use for several different projects.

Thanks for your help and sorry for my idiocy!

答案1

得分: 0

好的,以下是您要求的翻译内容:

我假设JFrame在您显式调用repaint之前不会绘制任何图像。

OnUpdate中有效,因为您在那里显式调用它,并且在循环迭代之间给组件一些时间来重新绘制自身。

deltaT = (System.currentTimeMillis() - lastShortTime) / 1000;
lastShortTime = System.currentTimeMillis();

while (AssessTime(FPS)) {
    . . . 
    display.repaint();
}

如果您只使用while循环 - 您的组件将没有足够的时间来重新绘制自身。

尝试这样做以验证我的假设:

while (true) {
    Thread.sleep(50);
    runtime.display.image = 随机生成的图像
    runtime.display.repaint();
}
英文:

Well, I assume JFrame won't draw any image until you call repaint explicitly.

It works in OnUpdate because you call it explicitly there and you give some time to the component to repaint itself between loop iterations.

deltaT = (System.currentTimeMillis()-lastShortTime)/1000;
        lastShortTime = System.currentTimeMillis();

while(AssessTime(FPS)) {
    . . . 
    display.repaint();
}

If you just do while loop - your component will not have enough time to redraw itself.

Try to do something like that to validate my assumption:

while(true) {
    Thread.sleep(50);
    runtime.display.image = (randomly generated image)
    runtime.display.repaint();
}

huangapple
  • 本文由 发表于 2020年4月5日 11:30:53
  • 转载请务必保留本文链接:https://java.coder-hub.com/61037679.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定