I would like to make a graphical representation of the audio signal.
I have a problem with entering data array to the method paint (Graphics g).
Data entered in the method setData(int intValue) works fine.
But if I want to print a data array in the method paint() I have zero values.
Why?
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class MyPlotter extends JPanel{
int width = 320;
int height = 130;
int frameSize;
int[] data;
public MyPlotter(int fSize){
setSize(width,height);
setPreferredSize(this.getSize());
this.frameSize = fSize;
data = new int[fSize+1];
}
public void setData(int[] intValue){
data = intValue;
// this works fine:
for (int i=0; i<440; i++)
System.out.println("setData "+data[i]);
repaint();
}
public void paint (Graphics g){
// some code:
// g.drawLine(...)
// g.setColor(...)
// etc...
for (int i = 0; i< frameSize-1;i++)
{
//ZERO values:
System.out.println("paint() "+(data[i]));
// g.drawline(...);
}
}
}
Edit:
Array Data is entered from MyPanel.class
import javax.swing.JPanel;
public class MyPanel extends JPanel {
private MyPlotter plotter;
public MyPanel(){
setSize(320,210);
plotter = new MyPlotter(440);
add(this.plotter,0);
}
public void setData(int[] data){
plotter.setData(data);
}
}
data = intValue;
Here you are psssing reference of intValue to data. If you change data intValue array also get changed.
Try this :
data = System.arraycopy( intValue, 0, data, 0, intValue.length);
Instead of :
data = intValue;
I think that possibly the "repaint()" method you called modifies the original array "intValue"
The assignment you have made data = intValue; only makes "data[]" a reference of your original array so as repaint is called seems like the data is reset or the reference is lost.If you want to copy the array you can do any of the following if a & b are two arrays:
b = Arrays.copyOf(a, a.length);
0r
b = new int[a.length];
System.arraycopy(a, 0, b, 0, b.length);
or
b = (int[]) a.clone();
or
int b[] = new int[a.length];
for (int i = 0; i < a.length; i++) {
b[i] = a[i];
}
Your code is OK. The problem is in the main method. Ensure you have added only one plotter to the panel.
public static void main(String[]args){
int[] mass = new int[]{1,2,3,4,5,6,7,8,9,10};
JFrame frame = new JFrame();
MyPanel mp = new MyPanel();
frame.add(mp);
frame.setSize(300, 300);
mp.setData(mass);
frame.setVisible(true);
}
Works well.
I'm sorry to answer my own post, but I changed the program completely.
I do not know if I can remove the code from the first post. So I put in a new post.
I changed a application but still have a problem with entering the array to another method.
Copy arrays by "Arrays.copyOf b = (a, a.length)" and changing the array as static does not fix a problem.
I can't enter array from setSignal() to getSignal() in OscilloscopeController class.
OscilloscopeController.java
import java.util.Arrays;
import java.util.Random;
public class OscilloscopeController {
private static int frameSize = (int) (44100 / 100F);
private int idx, numFramesToSkip = 10;
private static int[] toDraw = new int[frameSize];
private static int[] data = new int[frameSize];
public OscilloscopeController() {
for (int i = 0; i < frameSize; i++) {
toDraw[i] = 0;
data[i] = 0;
}
}
public void setSignal(int in) {
// Because the Model layer is off, I generate a test signal
Random randomGenerator = new Random();
int j = 0;
for (int i = 0; i < 44100; i++) {
int randomInt = randomGenerator.nextInt(32675 * 2) - (32675);
if (i % 4 == 0) {
j = randomInt;
}
in = j;
}
if (idx++ > frameSize * numFramesToSkip)
{
idx = 0;
}
else
{
if (idx < frameSize) {
data[idx] = in;
}
if (idx == frameSize)
{
// HERE IS PROBLEM. I'D LIKE THIS toDraw in getSignal()
toDraw = Arrays.copyOf(data, data.length);
}
}
}
public int[] getSignal() {
// IF UNCOMMENT BELOW WORKS FINE, OTHERWISE ZERO VALUES
/*
Random randomGenerator = new Random();
int j=0;
for (int i = 0; i < 440; i++) {
int randomInt = randomGenerator.nextInt(32675*2)-(32675);
if (i%4==0) j = randomInt;
toDraw[i]=j;
}
*/
for (int i = 0; i < frameSize; i++)
System.out.println("Controller.getSignal() = "+ toDraw[i]);
return toDraw;
}
}
MainPanel contains main method:
import java.awt.*;
import javax.swing.*;
public class MainPanel extends JPanel {
public static void main(String args[]) throws Exception {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new MainPanel());
frame.pack();
frame.setVisible(true);
}
});
}
private final OscilloscopeView oscView = new OscilloscopeView();
private final OscilloscopeController oscController = new OscilloscopeController();
public MainPanel() {
setPreferredSize(new Dimension(400, 200));
// a lot of other components here
oscView.setData(oscController.getSignal());
add(oscView);
}
}
OscilloscopeView.java
import javax.swing.JFrame;
import javax.swing.JPanel;
public class OscilloscopeView extends JPanel {
private OscPlotter plotter = new OscPlotter(441);;
public OscilloscopeView()
{
setSize(320,210);
add(this.plotter);
}
public void setData(int[] data){
plotter.setData(data);
}
}
OscPlotter.java
import java.awt.Color;
import java.awt.Graphics;
import java.util.Arrays;
import javax.swing.JPanel;
public class OscPlotter extends JPanel{
private int width = 320;
private int height = 130;
private float widthC;
private float heightC;
private int sampleSize;
private int frameSize;
private int[] toDraw;
private float x,prevX;
public OscPlotter(int fSize){
setSize(width,height);
setPreferredSize(this.getSize());
this.frameSize = fSize;
this.toDraw = new int[441];
sampleSize = 1;
}
public void setData(int[] data){
toDraw = Arrays.copyOf(data, data.length);
repaint();
}
#Override
public void paintComponent(Graphics g){
widthC = ((float)width/frameSize);
sampleSize = (16 == 16 ? 65536 : 256);
heightC = (((float)height-15)/sampleSize);
g.setColor(Color.black);
g.fillRect(0,0,width,height);
g.setColor(Color.gray);
for (int i = 1; i<height;i+=height/8)
g.drawLine(0,i,width,i);
for (int i = 1; i<width;i+=width/8)
g.drawLine(i,0,i,height);
g.setColor(Color.lightGray);
g.drawLine(0,(int)(height/2),width,(int)((height/2)));
g.setColor(Color.green);
x = 0;
for (int i = 0; i< frameSize-1;i++)
{
prevX = x;
x +=widthC;
// draw the read waveform data
g.drawLine ((int)prevX,(int)((height/2+toDraw[i]*heightC)),(int)x,(int)((height/2+toDraw[i+1]*heightC)));
}
}
}
Related
Edited as an MRE. I wasn't really sure how to write the code without extending JFrame or JPanel. This will reproduce the same error I am seeing. I am trying to render bars on the JPanel, but it seems that only the last iteration of the for loop in the PlotPanel class is being drawn.
package com.company;
import java.awt.*;
import javax.swing.*;
public class VisualizeAlgorithms {
public static int initPosX = 0;
public static int initPosY = 0;
public static int numBars = 200;
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
PlotFrame frame = new PlotFrame();
});
}
}
class PlotFrame extends JFrame {
PlotPanel plotPanel;
PlotFrame() {
plotPanel = new PlotPanel();
this.add(plotPanel);
this.setTitle("Plot");
this.setBackground(Color.DARK_GRAY);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.pack();
this.setVisible(true);
this.setResizable(false);
this.setLocationRelativeTo(null);
}
public int[] createArray(int numBars) {
int[] numsArray = new int[numBars];
for (int i = 0; i < numBars; i++) {
numsArray[i] = i + 1;
}
return numsArray;
}
}
class PlotPanel extends JPanel{
static final int PLOT_WIDTH = 1200;
static final int PLOT_HEIGHT = 800;
static final int MAX_BAR_HEIGHT = PLOT_HEIGHT;
static final int BAR_WIDTH = PLOT_WIDTH / VisualizeAlgorithms.numBars;
Dimension plotSize = new Dimension(PLOT_WIDTH, PLOT_HEIGHT);
PlotPanel() {
this.setPreferredSize(plotSize);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.CYAN);
draw(g);
}
public void draw(Graphics g){
int numBars = VisualizeAlgorithms.numBars;
for (int i = 0; i < numBars; i++) {
g.fillRect(BAR_WIDTH * i, VisualizeAlgorithms.initPosY, BAR_WIDTH, ((i+1)/numBars)*(MAX_BAR_HEIGHT));
}
}
}
Not sure if I can accept comments as answers, so I posted the answer here. It was indeed changing the rectangle height to int h = ((i+1)*MAX_BAR_HEIGHT/numBars). Thanks both to #AndrewThompson and #c0der not only for the answer but the additional information as well.
Aside: #c0der gave great advice re "when in doubt, print out". I recommend using this change:
public void draw(Graphics g){
int numBars = VisualizeAlgorithms.numBars;
for (int i = 0; i < numBars; i++) {
int x = BAR_WIDTH * I;
int y = VisualizeAlgorithms.initPosY;
int w = BAR_WIDTH;
int h = ((i+1)/numBars)*(MAX_BAR_HEIGHT);
System.out.println(String.format("x,y WxH: %1s,%1s %1sx%1s", x,y,w,h));
g.fillRect(x,y,w,h);
}
}
(print the values used for fillRect)
I'm working on a really basic bar chart which has to display 6 values. The problem I'm running into is that when i put the bars on the screen once they stay on the screen, and i cannot get them off. I've tried using the remove, repaint and revalidate functions but these all do not work.
What do I have to do to remove the bars so they don't clog up?
My code:
import javax.swing.*;
import java.awt.*;
import java.util.Collections;
public class BarChart extends JPanel
{
private JLabel[] bars;
public BarChart(int[] data)
{
update(data);
}
public void update(int[] data)
{
this.setSize(190, 155);
this.setLayout(null);
int max = 0;
for (int i = 0; i < 6; i++) {if (data[i] > max) {max = data[i];}}
bars = new JLabel[6];
for (int i = 0; i < 6; i++)
{
bars[i] = new JLabel();
bars[i].setOpaque(true);
bars[i].setBackground(Color.RED);
int height = (max != 0) ? (data[i]*155)/max : 0;
System.out.printf("%d, %d, %d,... ", height, data[i], max);
this.add(bars[i]);
bars[i].setSize(25, height);
bars[i].setLocation((31*i)+5, 155-height);
}
System.out.println("");
}
}
For your current code, you would need to call removeAll(), then revalidate() and repaint() on the JPanel would "solve" your problem, but you have other unrelated problems:
You're setting a component's size when you should be producing a preferred size -- this is what layout managers generally work with
You're using null layouts, a very dangerous thing
You're using a "magic" number as a for loop ending condition -- a VERY dangerous thing to do. How do you know that the data array has 6 and only items within it. What harm is there in simply using the data array's length as you've likely done hundreds of times before?
Instead, consider using more flexible code that will adapt to any size of data you give it and that avoids null layouts. For example consider the following code that draws the bars within the JPanel's paintComponent method:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class TestBarChart extends JPanel {
private static final int[] INIT_DATA = { 1, 2, 4, 5, 6, 9 };
protected static final int MIN_DATA_lENGTH = 5;
protected static final int MAX_DATA_LENGTH = 9;
private static final int MAX_VALUE = 9;
private static final int PREF_W = 300;
private static final int PREF_H = 240;
private BarChart2 barChart2 = new BarChart2(INIT_DATA, MAX_VALUE, PREF_W, PREF_H);
public TestBarChart() {
barChart2.setBorder(BorderFactory.createLineBorder(Color.BLUE));
JPanel chartsPanel = new JPanel(new GridLayout(1, 0));
chartsPanel.setLayout(new GridLayout(1, 0));
chartsPanel.add(barChart2);
JButton resetDataBtn = new JButton(new AbstractAction("Reset Data") {
#Override
public void actionPerformed(ActionEvent e) {
int dataLength = (int) ((MAX_DATA_LENGTH - MIN_DATA_lENGTH) * Math.random()) + MIN_DATA_lENGTH;
int[] data = new int[dataLength];
for (int i = 0; i < data.length; i++) {
data[i] = (int) (MAX_VALUE * Math.random()) + 1;
}
barChart2.setData(data, MAX_VALUE);
}
});
JPanel btnPanel = new JPanel();
btnPanel.add(resetDataBtn);
setLayout(new BorderLayout());
add(chartsPanel);
add(btnPanel, BorderLayout.PAGE_END);
}
private static void createAndShowGui() {
TestBarChart mainPanel = new TestBarChart();
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
#SuppressWarnings("serial")
class BarChart2 extends JPanel {
private static final double BAR_WIDTH = 0.90;
private int prefW;
private int prefH;
private static final Color BAR_COLOR = Color.RED;
private int[] data;
private int maxValue;
public BarChart2(int[] data, int maxValue, int prefW, int prefH) {
setData(data, maxValue);
this.prefW = prefW;
this.prefH = prefH;
}
public final void setData(int[] data, int maxValue) {
this.data = data;
this.maxValue = maxValue;
repaint();
}
public int[] getData() {
return data;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(BAR_COLOR);
// simple algebraic calculations on where to place the bars
double denom = data.length + 1 - BAR_WIDTH;
int barWidth = (int) ((getWidth() * BAR_WIDTH) / denom);
for (int i = 0; i < data.length; i++) {
int x = (int) (getWidth() * (i + 1 - BAR_WIDTH) / denom);
int height = (int) (getHeight() * data[i] / (double) maxValue);
int y = (int) (getHeight() - height);
g.fillRect(x, y, barWidth, height);
}
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(prefW, prefH);
}
}
Note that the bar charts re-size to fill the GUI if you re-size the GUI. Note that the chart accomodates any number of data bars, all depending on the length of the data array passed into it.
You need to repaint the component.
getContentPane().validate();
getContentPane().repaint();
I have a Problem, I tried to build up a code to visualise Functions.
package main;
import java.awt.*;
import java.awt.Graphics;
import javax.swing.JPanel;
public class MyPanel extends JPanel{
private static final long serialVersionUID = -6649271997955423098L;
#Override
public void paintComponent(Graphics g)
{
//super.paintComponents(g); only show code how it works
//g.setColor(Color.cyan);
//g.fillRect(10, 20, 35, 78);
paintStuff(g);
paintBackgroundComponents(g); // the navigation cross in the background
paintFunctions(g); //Both
leftPaintLineFunction(g); //with test Functions
rightPaintLineFunction(g);
}
/**
* Own Method for drawing lines. Needs Graphics g!
* #param g
*/
private void paintStuff(Graphics g)
{
g.setColor(Color.black);
g.drawString("Integral Veranschaulichung", (Main.length)-(Main.length/3),((Main.width) - (Main.width/12)));
}
private void paintBackgroundComponents(Graphics g)
{
g.drawLine((Main.length)/2, Main.width, (Main.length)/2, 0);
g.drawLine(0, (Main.width)/2, Main.length, (Main.width)/2);
g.setColor(Color.red);
g.drawString("X", (Main.length-(Main.length/8)) , ((Main.width/2) - (Main.width/80)));
g.drawString("Y", ((Main.length/2)+(Main.length/80)) , ((Main.width) - (Main.width/8)));
}
private void paintFunctions(Graphics g)
{
g.setColor(Color.blue);
for(int x=(0 - Main.length); x < Main.length; x++) //fills all possible values (limited through length)
{
g.drawOval((x) + (Main.length/2-1), Functions.solveTestFunction(x)+(Main.width/2-1), 3, 3);
}
}
//needs different methods for left and right Side
private void leftPaintLineFunction(Graphics g)
{
int [] pointOneX = new int [Main.length*2];
int [] pointOneY = new int [Main.length*2];
for(int x = 0; x < Main.length; x++)
{
pointOneX[x] = (((x)*(-1)) + (Main.length/2-1));
pointOneY[x]= (Functions.solveTestFunction(x) + (Main.width/2-1));
System.out.print(pointOneX[x]+" ");
System.out.print(pointOneY[x]);
}
g.drawPolyline(pointOneX, pointOneY, 100);
}
private void rightPaintLineFunction(Graphics g)
{
int [] pointOneX = new int [Main.length*2];
int [] pointOneY = new int [Main.length*2];
for(int x = 0; x < Main.length; x++)
{
pointOneX[x] = ((x) + (Main.length/2+2)); //no clue why 2?
pointOneY[x]= (Functions.solveTestFunction(x) + (Main.width/2));
System.out.print(pointOneX[x]+" ");
System.out.print(pointOneY[x]);
}
g.drawPolyline(pointOneX, pointOneY, 100);
}
}
My other class is:
package main;
public class Functions
{
int x = 0;
public static int solveTestFunction(int x) //simpel test function
{
int y=0;
y = (x^2)*(-1);//-1 cause the gui uses changed sides
return y;
}
}
And my main method is this one:
package main;
import javax.swing.JFrame;
public class Main {
static int length = 1000; // Playgrounds measures
static int width = 1000;
public static void main(String[] args)
{
JFrame frame = new JFrame("My Drawings");
MyPanel panel = new MyPanel();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(length, width); //playground
frame.add(panel);
frame.setVisible(true);
}
}
I split the method rightpaintLineFUnctions() in left and right. Cause that was the only way I get them to work. When I tried x*x for my testFunction everything worked quit good. But since Iwrote it in this form x^2 it didn't worked correct. Some help would be very nice.
I'm trying to show a 2D matrix when fill two text fields (rows and columns) but I don't know how to print the 2D matrix when this two text field are filled and the "Draw" button is pushed.
This is my code:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.io.*;
public class InputOutput extends JFrame{
JTextField mtf;
JTextField ntf;
JButton button;
public InputOutput(){
setLayout (new FlowLayout ());
mtf = new JTextField(10);
ntf = new JTextField(10);
add(mtf);
add(ntf);
button = new JButton("Dibujar");
add(button);
event e = new event();
button.addActionListener(e);
}
public class Cuadricula extends JComponent{
final int height = 30;
final int width = 30;
int posicionx=0;
int posiciony=0;
public Cuadricula(int x,int y){
setBounds(x,y,width+1, height+1);
}
#Override
public void paintComponent (Graphics g){
super.paintComponent(g);
g.drawRect(0,0,width,height);
}
}
public class event implements ActionListener{
public void actionPerformed(ActionEvent e){
String Sm = mtf.getText();
String Sn = ntf.getText();
int m = Integer.parseInt(Sm);
int n = Integer.parseInt(Sn);
Cuadricula casillas[] = new Cuadricula[m*n];
int i,j;
int k = 0;
while (k < m*n){
for(i=0; i < m; i++){
for(j=0; j < n; j++){
casillas[k] = new Cuadricula(i*30,j*30);
k++;
}
}
}
//HERE IS WHAT I DON'T KNOW HOW TO DO
for(int i = 0; i < 16; i++){
gui.getContentPane().add(casillas[i]);
}
}
}
public static void main(String[] args){
InputOutput gui = new InputOutput();
gui.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
gui.setSize(300,150);
gui.setTitle("Writer");
gui.setVisible(true);
gui.getContentPane().setLayout(null);
}
}
I have a window that dynamically updates the buffered image set on a JPanel using javax.swing.Timer
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
Whether I'm adding two dynamic lattice objects to the same panel
Multiple calls of repaint()
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. 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.
You overrode paintComponent but you invoke super.paintComponents(g). Notice the extra s you have at the end of paintComponents! This of course is unwanted and should be 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. It's always easier.
Also, you missed an important thing in SSCCE: the SHORT part. Meaning that you should remove anything unnecessary and have a single file to copy/paste.