JPanel を使用してバッファリングされた画像セットを動的に更新するウィンドウがあります。javax.swing.Timer
すべてが期待どおりに機能しますが、動的更新を呼び出すたびに、現在更新中の画像の下に別のバッファリングされた画像が表示されているようです。
トレーニング ボタン (動的更新をトリガーする) をクリックする前とクリックした後のウィンドウのイメージを以下に示します。
動的に更新される画像の下の画像が初期画面のように見えるため。以下を再確認しました
- 2 つのダイナミック ラティス オブジェクトを同じパネルに追加しているかどうか
- repaint() の複数回の呼び出し
- 動的ラティスの不要な初期化
私のコードではこれらのいずれも見つかりませんでした。コードは巨大であるため投稿できません。また、同じ動作を再現するための最小限のセットを作成しているときはいつでも、そこにはありません。したがって、この動作をトリガーするプロジェクトコードで何かが欠けているか、何かをしていると確信しています。これをデバッグする方法、またはなぜこのようなことをしているのかについての提案はありますか?
ありがとうございました
編集
SSCCE を以下に示します。実行している場合は、読み込みボタンをクリックしてから訓練ボタンをクリックして、エラーを取得します。
(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();
}
}
}