【问题标题】:Having trouble with dynamically updating a BufferedImage动态更新 BufferedImage 时遇到问题
【发布时间】:2013-06-19 19:39:03
【问题描述】:

我正在尝试在 JPanel 上呈现动态变化的图像。我已经尝试了很多事情,但我根本不知道该怎么做或我做错了什么,我快要发疯了。我是摇摆新手,这是我的程序中一个很小但很重要的部分,它使我能够看到自己在做什么。

简单的要求是在下面提到的代码中最初在 JPanel 中渲染的图片应该在每个刻度处更新为随机颜色。我无法让图像更新。相反,我正在尝试更新的图像中间出现另一个正方形,并且那个小正方形会动态变化。我不知道我做错了什么。请让我知道如何更正下面的代码,以便我可以更新整个图像。

谢谢。

代码如下

(MainTest.java)

import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.Timer;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;

public class MainTest extends JFrame {
static ImageEditor img ;
JPanel panel;
Timer to;

public MainTest()
{
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setSize(265, 329);
    getContentPane().setLayout(null);
    img =  new ImageEditor();
    panel = new ImageEditor();
    panel.setBounds(10, 11, 152, 151);
    panel.add(img);
    getContentPane().add(panel);

    JButton btnIterate = new JButton("Iterate");
    btnIterate.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {


            ThirdClass t = new ThirdClass(img);
            to = new Timer(10,t);
            to.start();             
        }

    });
    btnIterate.setBounds(10, 230, 89, 23);
    getContentPane().add(btnIterate);

}

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable()
    {
        public void run()
        {
            MainTest frame = new MainTest();
            //frame.getContentPane().add(imgx);
            frame.setVisible(true);
        }
    });

}
}

(ImageEditor.java)
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;

@SuppressWarnings("serial")
public class ImageEditor extends JPanel {

private static BufferedImage img = new BufferedImage(100, 100, 1);  
public ImageEditor() {
    render();
}

public void paintComponent(Graphics g) {
    if (img == null)
        super.paintComponents(g);
    else
        g.drawImage(img, 0, 0, this);
}


public void render() {

float cellWidth = 10;
float cellHeight = 10;

    int imgW = img.getWidth();
    int imgH = img.getHeight();
    float r, g, b;
    Graphics2D g2 = img.createGraphics();
    g2.setBackground(Color.black);
    g2.clearRect(0,0,imgW,imgH);
    for (int x=0; x<100; x++) {
        for (int y=0; y<100; y++) {
            r = (float)Math.random();
            g = (float)Math.random();
            b = (float)Math.random();
            g2.setColor(new Color(r,g,b));
            g2.fillRect((int)(x*cellWidth), (int)(y*cellHeight),
                        (int)cellWidth+1, (int)cellHeight+1);
        }
    }
    g2.setColor(Color.black);
    g2.dispose();
    repaint();
}

public BufferedImage getImage() {
    if (img == null)
        img = (BufferedImage)createImage(100, 100);

    return img;
}

public void setImage(BufferedImage bimg) {
    img = bimg;
}
}


(ThirdClass.java)
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;


public class ThirdClass implements ActionListener {

static ImageEditor mock;

public ThirdClass(ImageEditor img)
{
    mock = img;
    Train();
}

public void Train()
{
    mock.render();
}

@Override
public void actionPerformed(ActionEvent arg0) {
    Train();
}

    }

【问题讨论】:

  • 您将ImageEditor 放入ImageEditor。这就是你想要的?
  • 您可能想尝试实际修改图像本身,而不是每次都替换它,例如用BufferedImage.getRaster().setPixel(x, y, rgbArray)
  • @jag426 我实际上不明白你指的是什么。但是,如果它是关于 ImageEditor 类型的 JPanel 和图像本身,我只想将缓冲的图像放入 JPanel 并使其更新。
  • @AJMansfield 我试过这个方法,但它比解决它们和 setPixel 方法给我带来更多麻烦,这就是为什么我认为更新整个图像更容易。
  • 你有没有尝试过做一些更简单的事情,比如没有按钮?

标签: java swing jpanel bufferedimage


【解决方案1】:

来自代码:

img =  new ImageEditor();
panel = new ImageEditor();
panel.setBounds(10, 11, 152, 151);
panel.add(img);
getContentPane().add(panel);

您将img 定义为ImageEditor,但您可能打算将其定义为BufferedImage。然后你将它添加到panel,这是另一个ImageEditor - 但它是通过超类方法JPanel.add添加的,当你可能打算使用你编写的方法时,ImageEditor.setImage()

编辑:总结一下:

您描述的更新像素的小块是BufferedImage (img.img),位于您的ImageEditor img 内部,而ImageEditor panel 又位于ImageEditor panel 内部,而ImageEditor panel 本身位于小程序的内容窗格中。

  • MainTest 类中的static ImageEditor img 替换为BufferedImage img

  • MainTest 的无参数构造函数中的img = new ImageEditor 替换为img = new BufferedImage()

  • MainTest 的无参数构造函数中的panel.add(img) 替换为panel.setImage(img)

  • ThirdClass 类中的static ImageEditor mock 替换为BufferedImage mock

  • ThirdClass的构造函数中的ImageEditor img参数替换为BufferedImage img

  • 替换涉及img 的任何其他内容,以将其正确处理为BufferedImage

另外,虽然这个问题本身并不是任何程序故障的原因,但您应该将ThirdClass 中的Train() 方法重命名为train() 之类的名称,以便它匹配正确的java 样式。

【讨论】:

  • 感谢您指出这一点。是的!!!我打算将它作为 BufferedImage。由于我刚离开办公室,我现在无法查看。我明天去看看。
  • 我做了修改,但现在更新的小方块在那里,但这不是预期的结果。修改后的代码如下 img = new ImageEditor();panel = new JPanel();
  • @Synex 我已经编辑了我的答案,以便更清楚地了解我提出的更改。
  • 我检查了您的修改,但它不起作用。第三个要点将导致编译器错误,因为面板不包含 setImage(BufferedImage) 方法。第四个要点将导致 Train() 方法中的构建中断,因为无法调用 ImageEditor 的渲染方法。
  • @Synex 面板仍然应该是一个ImageEditor,它确实有一个setImage() 方法。
【解决方案2】:

在我最初发布上述问题后,我回到了基础并设法回答了我自己的问题。

我在下面插入了完整的代码,这样有同样问题的另一个用户就不必再经历同样的过程了。

我的错误非常微不足道。但是对于开始摇摆的人,我认为这可能会有所帮助

(MainTest.java)
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.Timer;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class MainTest extends JFrame { 

ImageEditor img;
JPanel panel;
Timer t;

public MainTest()
{
    setSize(600,600);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    getContentPane().setLayout(null);

    img = new ImageEditor();
    panel = img;
    panel.setBounds(0, 0, 510, 510);
    getContentPane().add(panel);

    JButton btnStart = new JButton("Start");
    btnStart.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            test();
        }
    });
    btnStart.setBounds(0, 528, 89, 23);
    getContentPane().add(btnStart);
}

private void test() {
    Train tx = new Train(img);
    t = new Timer(100, tx);
    t.start();
}

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable()
    {
        public void run()
        {
            MainTest frame = new MainTest();
            frame.setVisible(true);
        }
    });

  }

}

(ImageEditor.java)
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;

@SuppressWarnings("serial")
public class ImageEditor extends JPanel  {

private static BufferedImage img = new BufferedImage(500, 500, 1);  

public ImageEditor() {
    setLayout(null);
}

public void paintComponent(Graphics g) {
    if (img == null)
        super.paintComponents(g);
    else
        g.drawImage(img, 0, 0, this);
}

public void render() {

float cellWidth = 10;
float cellHeight = 10;

    int imgW = img.getWidth();
    int imgH = img.getHeight();
    float r, g, b;
    Graphics2D g2 = img.createGraphics();
    g2.setBackground(Color.black);
    g2.clearRect(0,0,imgW,imgH);
    for (int x=0; x<100; x++) {
        for (int y=0; y<100; y++) {
            r = (float)Math.random();
            g = (float)Math.random();
            b = (float)Math.random();
            g2.setColor(new Color(r,g,b));
            g2.fillRect((int)(x*cellWidth), (int)(y*cellHeight),
                        (int)cellWidth+1, (int)cellHeight+1);
        }
    }
    g2.setColor(Color.black);
    g2.dispose();
    repaint();
}

public BufferedImage getImage() {
    if (img == null)
        img = (BufferedImage)createImage(500, 500);

    return img;
}

public void setImage(BufferedImage bimg) {
    img = bimg;
}

}

(Train.java this class was named ThirdClass.java in my question)
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Train implements ActionListener {

ImageEditor temp;

Train(ImageEditor img)
{
    temp = img;
}

public void train()
{
    temp.render();  
}

@Override
public void actionPerformed(ActionEvent e) {
    train();
}

}

感谢所有评论并回答我问题的人。

【讨论】:

    猜你喜欢
    • 2020-03-02
    • 2023-02-05
    • 2019-04-05
    • 2020-11-29
    • 2020-11-10
    • 1970-01-01
    • 1970-01-01
    • 2021-04-07
    • 1970-01-01
    相关资源
    最近更新 更多