简体   繁体   English

替代将许多对象绘制到JPanel上

[英]Alternative to painting many objects onto a JPanel

I will be rewriting the below class to use the constructor and do a few smarter things (rather than the four producers() like methods - so don't worry about that. 我将重写下面的类来使用构造函数并做一些更聪明的事情(而不是像方法那样的四个producer() - 所以不要担心。

At the moment I loop through these four array lists and then paint objects onto a JPanel. 目前,我遍历这四个数组列表,然后将对象绘制到JPanel上。 After about 2-3000 objects, this can result in some significant latency. 在大约2-3000个对象之后,这可能导致一些显着的延迟。

What could I use as an alternative to these array lists? 我可以用什么来替代这些数组列表? Would some type of serialization into JSON/XML work? 将某些类型的序列化转换为JSON / XML吗? In my professional coding (rather than this simple side project) I work with a massive system that uses DataNucleus to convert model classes to a table structure in SQL - I feel like that would be massive overkill for my fun side project. 在我的专业编码(而不是这个简单的侧面项目)中,我使用一个庞大的系统,使用DataNucleus将模型类转换为SQL中的表结构 - 我觉得这对我有趣的项目来说将是一个巨大的过度杀伤力。 Thoughts? 思考?

public class Life {
PlayPanel panel;
public int prodSeed;
public int herbSeed;
public int predSeed;
public int decoSeed;
public ArrayList<Producer> prodStore = new ArrayList<Producer>();
public ArrayList<Herbivore> herbStore = new ArrayList<Herbivore>();
public ArrayList<Predator> predStore = new ArrayList<Predator>();
public ArrayList<Decomposer> decoStore = new ArrayList<Decomposer>();


public Life() {
}

public void setPanel(PlayPanel p) {
    panel = p;
}
public void producers() {
    for(int j = 0; j < prodSeed; j++) {
        Producer p = new Producer(panel.life);
        prodStore.add(p);
    }
    panel.producerPaint = true;
}
public void herbivores() {
    for(int j = 0; j < herbSeed; j++) {
        Herbivore h = new Herbivore(panel.life);
        herbStore.add(h);
    }
    panel.herbivorePaint = true;
}
public void predators() {
    for(int j = 0; j < predSeed; j++) {
        Predator p = new Predator(panel.life);
        predStore.add(p);
    }
    panel.predatorPaint = true;
}
public void decomposers() {
    for(int j = 0; j < decoSeed; j++) {
        Decomposer d = new Decomposer(panel.life);
        decoStore.add(d);
    }
    panel.decomposerPaint = true;
}
public void beginAction() {
    for (int j = 0; j < prodStore.size(); j++) {
        prodStore.get(j).behavior();panel.repaint();        
    }
    for (int j = 0; j < herbStore.size(); j++) {
        herbStore.get(j).behavior();panel.repaint();
    }
    for (int j = 0; j < predStore.size(); j++) {
        predStore.get(j).behavior();panel.repaint();
    }
    for (int j = 0; j < decoStore.size(); j++) {
        decoStore.get(j).behavior();panel.repaint();
    }
    //Use booleans between these for loops to not repaint an extra amount of action

}

Horribly painful paintComponent method in the JPanel class: JPanel类中的paintComponent方法非常痛苦:

public void paintComponent(Graphics g) {
    super.paintComponent(g);
    if(producerPaint == true) {
        //int j = 0;

        while(j < life.prodStore.size()) {
            g.setColor(new Color(19,145,14));
            g.fillOval(life.prodStore.get(j).getxAxis(), life.prodStore.get(j).getyAxis(), life.prodStore.get(j).getxSize(), life.prodStore.get(j).getySize());
            j++;
        }
        j=0;
    }
    if(herbivorePaint == true) {
        //int j = 0;

        while(j < life.herbStore.size()) {
            g.setColor(new Color(228,226,158));
            g.fillOval(life.herbStore.get(j).getxAxis(), life.herbStore.get(j).getyAxis(), life.herbStore.get(j).getxSize(), life.herbStore.get(j).getySize());
            j++;
        }
        j=0;
    }
    if(predatorPaint == true) {
        //int j = 0;

        while(j < life.predStore.size()) {
            g.setColor(new Color(207,87,87));
            g.fillOval(life.predStore.get(j).getxAxis(), life.predStore.get(j).getyAxis(), life.predStore.get(j).getxSize(), life.predStore.get(j).getySize());
            j++;
        }
        j=0;
    }
    if(decomposerPaint == true) {
        //int j = 0;

        while(j < life.decoStore.size()) {
            g.setColor(Color.white);
            g.fillOval(life.decoStore.get(j).getxAxis(), life.decoStore.get(j).getyAxis(), life.decoStore.get(j).getxSize(), life.decoStore.get(j).getySize());
            j++;
        }
        j=0;
    }
}

As a pertinent side note: I will be reworking away from the use of booleans as I work through this code (project is a year or two old, before I knew what I was doing)! 作为一个相关的旁注:当我完成这个代码时,我将重新使用布尔值(项目是一两年前,在我知道我在做什么之前)!

Drawing many, many items onto a component isn't a problem, but it shouldn't be happening inside of paintComponent . 在组件上绘制许多很多项都不是问题,但不应该在paintComponent发生。 What you want to do is have a separate image (ex. BufferedImage ), paint onto that image, and then your paintComponent is only responsible for painting that image onto the JPanel. 你想要做的是有一个单独的图像(例如BufferedImage ),绘制到该图像上,然后你的paintComponent只负责将该图像绘制到JPanel上。 Hence, your user is not seeing all these things painted one by one. 因此,您的用户并未逐一看到所有这些东西。 They only see the final product. 他们只看到最终产品。

Search "Double Buffering in Java" for nice demos on this idea. 搜索“Java中的双缓冲”以获得有关此想法的精彩演示。

As for the data structures, keeping 4 lists is fine, but you may want to have more abstract drawing utilities that are shared amongst all your objects. 至于数据结构,保留4个列表很好,但您可能希望拥有更多抽象绘图实用程序,这些实用程序在所有对象之间共享。 For instance, the way you draw them all is about the same, except for the Color, so create a drawing method that accepts the superclass (ex. BiologyObject ) to any of those subclasses (ex. Producer , Decomposer , etc) as the parameter. 例如,除了Color之外,绘制它们的方式大致相同,因此创建一个绘图方法, BiologyObject类(例如BiologyObjectBiologyObject任何这些子类(例如ProducerDecomposer等)作为参数。 Let me know if that doesn't make sense. 如果这没有意义,请告诉我。

UPDATE: proper way to draw onto JPanel 更新:正确的方式来绘制到JPanel

private BufferedImage image;

public MyClass() {
    image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_ARGB);
}

public void paintOntoImage() {
    //here is where you would draw all the things that you currently have in your paintComponent method
    Graphics2D g = (Graphics2D) image.getGraphics();
    g.setColor(Color.white);
    g.fillRect(0, 0, WIDTH, HEIGHT);

    //now you can call "g.fillOval" or any other methods on "g"
}

public void paintComponent(Graphics g) {
    g.drawImage(image, 0, 0, null);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM