简体   繁体   English

动态更新JPanel时不希望的重新绘制

[英]Undesirable repaint of a JPanel when dynamically updated

I have a window that dynamically updates the buffered image set on a JPanel using javax.swing.Timer 我有一个窗口,可以使用javax.swing.Timer动态更新JPanel上设置的缓冲图像。

Everything works as expected but every time I invoke the dynamic update there seems to be another buffered image displayed below the currently updating one. 一切都按预期工作,但是每次我调用动态更新时,似乎在当前正在更新的图像下方显示了另一个缓冲图像。

The image of the window before and after clicking the train button (which triggers the dynamic update) is given below. 单击火车按钮之前和之后(触发动态更新)的窗口图像如下。

在此处输入图片说明

Since the image below the dynamically updating image looks like the initial screen. 由于动态更新图像下面的图像看起来像初始屏幕。 I rechecked the following 我重新检查了以下内容

  1. Whether I'm adding two dynamic lattice objects to the same panel 是否将两个动态晶格对象添加到同一面板
  2. Multiple calls of repaint() 多次调用repaint()
  3. Unwanted initialization of the dynamic lattice 动态晶格的不必要的初始化

I could not find any of these in my code. 我在代码中找不到这些。 I cannot post the code since it is huge and whenever I'm creating a minimal set to reproduce the same behavior it is not there. 我无法发布代码,因为它太大了,每当我创建最小集来重现相同行为时,它就不存在了。 So I'm sure I'm missing something or doing something on my project code which triggers this behavior. 因此,我确定我的项目代码中缺少某些东西或在做某些事情来触发此行为。 Any suggestions on how to debug this or why it is doing something like this? 关于如何调试它或为什么这样做的建议?

Thank you 谢谢

EDIT 编辑

SSCCE is give below. SSCCE在下面给出。 If executing, click the load button followed by the train button to get the error. 如果执行,请单击加载按钮,然后单击火车按钮以获取错误。

(MapScreen.java - Main Class)
package test;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import java.awt.Font;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import test.DisplayLattice;
import test.SelfOrganizingMap;

public class MapScreen extends JFrame {

private double NUM_ITERATIONS = 0.0;
private double ETA = 0.0;
private double SPREAD_FACTOR = 0.0;
private double RADIUS = 0.0;
private int WIDTH = 0;
private int HEIGHT = 0;
private SelfOrganizingMap SOM = null;
private Timer REFRESH_TIMER = null; 
private JPanel pnlMap;
private JButton btnLoadParameters;
private JButton btnTrain;
private DisplayLattice displayScreen;


public MapScreen(double iterations, double learningRate, double spreadFactor, double radius, int option, int width, int height, int mapOption) {

    NUM_ITERATIONS = iterations;
    ETA = learningRate;
    SPREAD_FACTOR = spreadFactor;
    RADIUS = radius;
    WIDTH = width;
    HEIGHT = height;

    setType(Type.UTILITY);
    setResizable(false);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setTitle("Map");
    setSize(650, 800);
    setLocation(150,150);
    getContentPane().setLayout(null);

    displayScreen = new DisplayLattice();
    pnlMap = displayScreen;
    pnlMap.setBounds(6, 130, 600, 600);
    getContentPane().add(pnlMap);


    btnLoadParameters = new JButton("Load Parameters");
    btnLoadParameters.setFont(new Font("Tahoma", Font.PLAIN, 11));
    btnLoadParameters.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0)
        {
            SOM = new SelfOrganizingMap(10000,0,0,13,displayScreen);
        }
    });
    btnLoadParameters.setBounds(192, 46, 126, 23);
    getContentPane().add(btnLoadParameters);

    btnTrain = new JButton("Train");
    btnTrain.setFont(new Font("Tahoma", Font.PLAIN, 11));
    btnTrain.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            initialObjectSetUp();
        }
    });
    btnTrain.setBounds(192, 72, 62, 23);
    getContentPane().add(btnTrain); 
}

private void initialObjectSetUp()
{
    SOM.initTrainSOM(null, 100, 0.25);
    REFRESH_TIMER = new Timer(100, SOM);
    REFRESH_TIMER.start();
}


public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable()
    {
        public void run()
        {
            MapScreen frame = new MapScreen(100,0.25,0.0,0.0,1,100,0,0);
            frame.setVisible(true);
        }
    });

}   
}

(SelfOrganizingMap.java)
package test;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class SelfOrganizingMap implements ActionListener {

private Node[][] SOM = null;
private double[][] NORM_MAP = null; //holds the L2 norm of each vector in the SOM[][].
@SuppressWarnings("unused")
private int GRID_OPTION = 0;
private int INPUT_DIMENSION = 0;
private int NUMER_OF_ITERATIONS = 0;
private int CURRENT_ITERATION=0;
private int SOM_HORIZONTAL_LENGTH = 0;
private int SOM_VERTICAL_LENGTH = 0;
private double INITIAL_LEARNING_RATE = 0.0;
private double LEARNING_RATE = 0.0;
private double MAX_RADIUS = 0.0; //radius at first epoch (t = 0)
private double RADIUS = 0.0;
private double TIME_STEP = 0.0; //lambda of X(t) = t0 * exp(-t/lambda)
private String INPUT_SAMPLES = null;
private DisplayLattice DISPLAY_SCREEN = null;


public SelfOrganizingMap(int numberOfNodes, int depth, int grid, int inputDimensison, DisplayLattice screen)
{
    INPUT_DIMENSION = inputDimensison;

    if(grid == 0)
    {
        int side = (int)Math.sqrt(numberOfNodes);
        SOM = new Node[side][side];
        NORM_MAP = new double[side][side];
        GRID_OPTION = grid;
        MAX_RADIUS = side/2;
        DISPLAY_SCREEN = screen;
    }


    RADIUS = MAX_RADIUS;
}

public void initTrainSOM(String input, int iterations, double learningRate)
{

    NUMER_OF_ITERATIONS = iterations;
    INITIAL_LEARNING_RATE = learningRate;
    LEARNING_RATE = INITIAL_LEARNING_RATE;
    TIME_STEP = NUMER_OF_ITERATIONS/Math.log(MAX_RADIUS);
    INPUT_SAMPLES = input;

}

private void singleCompleteRun()
{
    DISPLAY_SCREEN.render();
    System.out.println(CURRENT_ITERATION);
}

@Override
public void actionPerformed(ActionEvent e) {
    // TODO Auto-generated method stub
    if(CURRENT_ITERATION <= NUMER_OF_ITERATIONS)
    {
        singleCompleteRun();    
        CURRENT_ITERATION++;
    }

}

}

(DisplayLattice.java)
package test;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import javax.swing.*;

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

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

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


public void render() {

float cellWidth = 100;
float cellHeight = 100;

    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;
}
}
(Node.java - Structure class for the SOM)
package test;
public class Node {

private int DIMENSION = 0;  
private int POSITION_X = 0;
private int POSITION_Y = 0; 
private double ACTIVATION_VALUE = 0.0; 

public Node(int Dimensions, int x, int y)
{
    DIMENSION = Dimensions; 
    setWeightVector();
    POSITION_X = x;
    POSITION_Y = y;
}

public int getX() {
    return POSITION_X;
}

public int getY() {
    return POSITION_Y;
}

public double getACTIVATION_VALUE() {
    return ACTIVATION_VALUE;
}

public void setPOSITION_X(int x) {
    POSITION_X = x;
}

public void setPOSITION_Y(int y) {
    POSITION_Y = y;
}

public void setACTIVATION_VALUE(double y) {
    ACTIVATION_VALUE= y;
}

private void setWeightVector()
{
    double temp[] = new double[DIMENSION];

    for(int i = 0; i<temp.length ; i++)
    {
        temp[i] =  Math.random();
    }

}

}

The problem is your DiaplyLattice class. 问题是您的DiaplyLattice类。

You overrode paintComponent but you invoke super.paintComponents(g) . 您覆盖了paintComponent但是调用了super.paintComponents(g) Notice the extra s you have at the end of paintComponents ! 注意额外的s ,你必须在年底paintComponents This of course is unwanted and should be super.paintComponent(g); 当然这是不需要的,应该是super.paintComponent(g);

I would have you method as follow: 我要你的方法如下:

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

Now, just as a good advice/tip to give, don't use null layout and rather use LayoutManager 's and possibly use several level of nesting. 现在,就像给出的一个很好的建议/技巧一样,不要使用null布局,而要使用LayoutManager ,并且可能使用多层嵌套。 It's always easier. 总是比较容易。

Also, you missed an important thing in SSCCE: the SHORT part. 另外,您错过了SSCCE中的重要内容:SHORT部分。 Meaning that you should remove anything unnecessary and have a single file to copy/paste. 这意味着您应该删除所有不必要的内容,并复制/粘贴一个文件。

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

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